Python Modeling Tool

pymt is the Python Modeling Toolkit. It is an Open Source Python package, developed by the Community Surface Dynamics Modeling System (CSDMS), that provides the tools needed for coupling models that expose the Basic Model Interface (BMI).

pymt in three points:

  • Tools for coupling models of disparate time and space scales
  • A collection of Earth-surface models
  • Extensible plug-in framework for adding new models

What does it look like? Here is an example of a simple pymt program:

from pymt.models import Cem, Waves

waves = Waves()
cem = Cem()

waves.initialize(*waves.setup())
cem.initialize(*cem.setup())

for time in range(1000):
    waves.update()
    angle = waves.get_value("wave_angle")
    cem.set_value("wave_angle", angle)
    cem.update()

User Guide

If you are looking for information on using pymt to configure, run, and couple models, this part of the documentation is for you.

The Python Modeling Toolkit

Documentation Status Build Status Coverage Status License: MIT Code style: black Launch Binder

Quick links:

PyMT is an Open Source Python package, developed by the Community Surface Dynamics Modeling System (CSDMS), that provides the necessary tools used for the coupling of models that expose the Basic Model Interface (BMI). It contains:

  • Tools necessary for coupling models of disparate time and space scales (including grid mappers)
  • Time-steppers that coordinate the sequencing of coupled models
  • Exchange of data between BMI-enabled models
  • Wrappers that automatically load BMI-enabled models into the PyMT framework
  • Utilities that support open-source interfaces (UGRID, SGRID, CSDMS Standard Names, etc.)
  • A collection of community-submitted models, written in a variety of programming languages, from a variety of process domains - but all usable from within the Python programming language
  • A plug-in framework for adding additional BMI-enabled models to the framework

This material is based upon work supported by the National Science Foundation under Grant No. 1831623, Community Facility Support: The Community Surface Dynamics Modeling System (CSDMS).

Quickstart

Here’s the fast path to using pymt. If you want to dig deeper, links are provided at each step to more detailed information either here in the User Guide or elsewhere.

If you encounter any problems when installing or running pymt, please visit us at the CSDMS Help Desk and explain what occurred.

Install conda

Anaconda is a free, open-source, Python distribution that contains a comprehensive set of packages for scientific computing. If you don’t have conda installed, the Anaconda installation guide can help you through the process.

Install pymt

Once you’ve installed conda, You can get pymt directly from conda-forge:

$ conda install pymt -c conda-forge

Installing into a conda environment is strongly recommended. Check the installation guide for more detailed information about installing pymt.

Install a model

Hydrotrend is a hydrological water balance and transport model that simulates water discharge and sediment load at a river outlet. It’s also one of the models available in pymt. Install Hydrotrend into pymt with:

$ conda install pymt_hydrotrend -c conda-forge

Check that the model has been installed by starting a Python session and importing pymt:

>>> import pymt.models
=> models: Hydrotrend

Keep this Python session open; we’ll use it for the examples that follow.

Run a model

Now that Hydrotrend has been installed into pymt, import it into your Python session and create an instance:

>>> from pymt.models import Hydrotrend
>>> model = Hydrotrend()

To run a model, pymt expects a model configuration file. Get the default configuration for Hydrotrend:

>>> cfg_file, cfg_dir = model.setup()

Start the model, setting its initial conditions, by calling its initialize method:

>>> model.initialize(cfg_file, cfg_dir)

The model is now ready to run. For reference, show the current time in the model.

>>> model.time
0.0

Now call the update method to advance the model by a single time step:

>>> model.update()
>>> model.time
1.0

What units are associated with this time step? (Picoseconds? Parsecs?) Find out with the time_units property:

>>> model.time_units
'd'

The Hydrotrend model exposes a set of output variables, as shown by the get_output_var_names method:

>>> for var in model.get_output_var_names():
...     print(var)
...
atmosphere_bottom_air__domain_mean_of_temperature
channel_exit_water_sediment~suspended__mass_flow_rate
channel_exit_water_flow__speed
channel_entrance_water_sediment~bedload__mass_flow_rate
channel_exit_water__volume_flow_rate
channel_exit_water_x-section__width
channel_exit_water_x-section__depth
channel_entrance_water__volume_flow_rate
atmosphere_water__domain_mean_of_precipitation_leq-volume_flux
channel_exit_water_sediment~bedload__mass_flow_rate
channel_exit_water_sediment~suspended__mass_concentration

With the get_value method, find the current value of the mean water discharge at the river mouth through its descriptive CSDMS Standard Name. And because the Standard Name is long, let’s first store it in a variable:

>>> discharge_sn = 'channel_exit_water__volume_flow_rate'
>>> model.get_value(discharge_sn)
array([ 1.1])

What units are attached to this discharge value? Find out with the get_var_units method:

>>> model.get_var_units(discharge_sn)
'm^3 / s'

To finish, let’s run the model to completion, storing the discharge values for future use. First, calculate how many time steps remain in the model:

>>> n_steps = int(model.end_time / model.time_step) - 1

Follow this by importing Python’s NumPy library, then use it to create an empty array to hold the discharge values:

>>> import numpy as np
>>> discharge = np.empty(n_steps)

Now use a loop to advance the model to its end, storing the discharge value at each time step:

>>> for t in range(n_steps):
...     discharge[t] = model.get_value(discharge_sn)
...     model.update()

Complete the model run by calling the finalize method:

>>> model.finalize()

View results

Let’s plot the daily mean water discharge values generated by the model. Start by importing Python’s matplotlib library, used for generating a variety of publication-quality figures:

>>> import matplotlib.pyplot as plt

Then set up a line plot of the discharge values:

>>> plt.plot(discharge, 'r')

Nothing appears on the screen yet; this statement only configures the plot. However, a plot isn’t complete until it has appropriate labels. Add some with:

>>> plt.title('Mean Daily Discharge at River Mouth')
>>> plt.xlabel('Simulation Time (d)')
>>> plt.ylabel('Discharge ($m^3 s^{-1}$)')

Now display the plot:

>>> plt.show()
Mean daily water discharge from the Hydrotrend model.

A more detailed example of using Hydrotrend can be found in the notebooks/hydrotrend Jupyter Notebook. An expanded description of the pymt methods used in this example can be found in the Usage section.

Installation

There are two ways to install pymt on your local machine:

If you plan to use pymt to run and couple models, installing a stable release is a good option. However, if you intend to develop with pymt, possibly modifying it, it’s best to install it from source.

If you encounter any problems when installing pymt, please visit us at the CSDMS Help Desk and explain what occurred.

Stable release

We strongly recommend using conda to install and run pymt. If you don’t have conda installed, the Anaconda installation guide can help you through the process.

Once you’ve installed conda, add the conda-forge channel to the list of enabled conda channels on your machine:

$ conda config --add channels conda-forge

We advise installing pymt into a conda environment. Conda environments can easily be created and discarded. Create an environment for pymt with:

$ conda create -n pymt python=3

Once the conda environment has been created, activate it with:

$ source activate pymt

Install pymt into this conda environment with:

$ conda install pymt

Note that pymt is built on several open source software libraries, so it may take a few minutes for conda to find, download, and install them.

You’re now ready to start using pymt. Check the installation by starting a Python session and importing pymt:

>>> import pymt.models
=> models: (none)

By default, no models are installed with pymt. Instructions for installing models into pymt are given in the section Install a model.

From source

We strongly recommend using conda to install and run pymt. If you don’t have conda installed, the Anaconda installation guide can help you through the process.

Once you’ve installed conda, add the conda-forge channel to the list of enabled conda channels on your machine:

$ conda config --add channels conda-forge

We advise installing pymt into a conda environment. Conda environments can easily be created and discarded. Create an environment for pymt with:

$ conda create -n pymt python=3

Once the conda environment has been created, activate it with:

$ source activate pymt

The source code for pymt can be downloaded from the Github repo.

You can either clone the public repository:

$ git clone git://github.com/csdms/pymt

Or download the tarball:

$ curl -OL https://github.com/csdms/pymt/tarball/master

Once you have a copy of the source, install the pymt dependencies into the conda environment you created above:

$ conda install --file=requirements.txt

Then install pymt with:

$ python setup.py install

You’re now ready to start using pymt. Check the installation by starting a Python session and importing pymt:

>>> import pymt.models
=> models: (none)

By default, no models are installed with pymt. Instructions for installing models into pymt are given in the section Install a model.

Usage

In this section, we describe the primary programmatic elements of pymt and explain how to use them to configure, run, and couple models.

We assume here that you have installed pymt, following the instructions in the Installation guide. Below, we’ll use the CEM and Waves models. Install them with:

$ conda install pymt_cem

Loading pymt

pymt is distributed as a Python package. To use pymt, it has to be imported into a Python session. For example, the entire package can be loaded with a single import:

>>> import pymt

Alternately, models that have been installed into pymt can be imported individually:

>>> from pymt.models import Waves
=> models: Cem, Waves

Either technique is acceptable, but there’s a slight Pythonic preference for loading individual models as needed. We’ll use this technique in the remainder of this section. In either case, pymt must always be imported into a Python session before it can be used.

Instantiating a model

After importing a pymt model into a Python session, you can create an instance of it (also known as an object):

>>> model = Waves()

It is through an instance that we can configure, interact with, and run a model in pymt. The instance we’ve created here, model, contains information (called properties or data) about the Waves model (e.g., its inputs and outputs, its time step, its spatial domain), as well as programs (called methods) that allow access to these data. The sections below describe some of the data and methods that are associated with a model instance in pymt.

Model setup

The setup method configures a model run. It’s used to:

  • set individual model input variables,
  • generate a model configuration file for a run, and
  • make a run directory.

Depending on a user’s preference, setup can be invoked in different ways. For example, given a Waves instance like the one created in the previous section, a basic call to setup would be:

>>> cfg_file, cfg_dir = model.setup()

This creates a model configuration file with default parameters in a run directory in a temporary location on the filessytem. It returns the name of configuration file and the path to the run directory:

>>> print(cfg_file, cfg_dir)
waves.txt /tmp/tmpeydq6usd

Note that the two outputs could also be grouped into a single variable; e.g.:

>>> args = model.setup()

Alternately, the run directory can be specified. For example, to run the model in the current directory:

>>> cfg_dir = '.'
>>> model.setup(cfg_dir)

Here, we didn’t use the outputs from setup because the run directory has been specified, and the configuration file is created within it.

Model inputs can also be configured with setup. Find the default values of the inputs by querying the parameters property of the model:

>>> for name, value in model.parameters:
...     print(name, '=', value)
...
run_duration = 3650
incoming_wave_height = 2.0
incoming_wave_period = 7.0
angle_highness_factor = 0.2
angle_asymmetry = 0.5

Configure the model to use an incoming wave height of 3.5, instead of the default 2.0, meters:

>>> model.setup(cfg_dir, incoming_wave_height=3.5)

Check the parameters property to verify that the model inputs have been updated.

Lifecycle methods

The initialize and finalize methods are used to start and complete a model run. Initialize sets the initial conditions for a model, while finalize cleans up any resources allocated for the model run.

Initialize requires a model configuration file. The run directory is an optional argument; if it’s not provided, the current directory is assumed.

Using the Waves model as an example, the steps to import, instantiate, set up, and initialize the model are:

>>> from pymt.models import Waves
>>> waves = Waves()
>>> config_file, config_dir = waves.setup()
>>> waves.initialize(config_file, dir=config_dir)

Note that if the outputs from setup had been stored in a single variable, the values could be unpacked in the call to initialize:

>>> config = waves.setup()
>>> waves.initialize(*config)

Further, if a model configuration file already exists, it can be passed directly to initialize, and the call to setup could be omitted.

Finalize ends a model run. It takes no arguments:

>>> waves.finalize()

No further operations can be performed on a model after it has been finalized.

Time

The start time, end time, and current time in a model are reported through a model’s Basic Model Interface and made available in pymt through three properties: start_time, end_time, and time. To demonstrate these properties, create and initialize a new instance of the Waves model:

>>> waves = Waves()
>>> config = waves.setup()
>>> waves.initialize(*config)

then access these time properties with:

>>> waves.start_time
0.0
>>> waves.end_time
3650.0
>>> waves.time
0.0

Use the time_units property to see the units associated with these time values:

>>> waves.time_units
'd'

CSDMS recommends using time unit conventions from Unidata’s UDUNITS package.

Finally, find the model time step through the time_step property:

>>> waves.time_step
1.0

Updating model state

A model can be advanced through time, one step at a time, with the the update method.

Update the instance of Waves created in the previous section by a single time step, checking the time before and after the update:

>>> waves.time
0.0
>>> waves.update()
>>> waves.time
1.0

Although we verified that the model time has been updated, it would be more interesting to see model variables change. In the next two sections, we’ll find what variables a model exposes, and how to get their values.

Getting variable names

What variables does a model expose for input and output, for exchange with other models? These aren’t internal variables in the model source code (like loop counters), but rather variables that have CSDMS Standard Names and are exposed through a model’s Basic Model Interface.

The input_var_names and output_var_names properties list the variables exposed by a model. Find the variables exposed by our Waves instance:

>>> waves.input_var_names
('sea_surface_water_wave__height',
 'sea_surface_water_wave__period',
 'sea_shoreline_wave~incoming~deepwater__ashton_et_al_approach_angle_highness_parameter',
 'sea_shoreline_wave~incoming~deepwater__ashton_et_al_approach_angle_asymmetry_parameter')

>>> waves.output_var_names
('sea_surface_water_wave__min_of_increment_of_azimuth_angle_of_opposite_of_phase_velocity',
 'sea_surface_water_wave__azimuth_angle_of_opposite_of_phase_velocity',
 'sea_surface_water_wave__mean_of_increment_of_azimuth_angle_of_opposite_of_phase_velocity',
 'sea_surface_water_wave__max_of_increment_of_azimuth_angle_of_opposite_of_phase_velocity',
 'sea_surface_water_wave__height',
 'sea_surface_water_wave__period')

In each case, the variable names are returned in a tuple. The names tend to be quite descriptive, in order to aid in semantic matching between models. In practice, it’s often convenient to use a common short name for a variable instead of its Standard Name.

Getting and setting variables

The values of variables exposed by a model can be accessed with the get_value method and modified with the set_value method. Each of these methods takes a variable name (a CSDMS Standard Name) as input.

As shown in the section above, the variable sea_surface_water_wave__height is both an input and an output variable in Waves. Find its current value:

>>> waves.get_value('sea_surface_water_wave__height')
array([ 2.])

In pymt, variable values are stored as NumPy arrays.

Assign a new wave height value in the model:

>>> waves.set_value('sea_surface_water_wave__height', 3.5)

and check the result with get_value:

>>> waves.get_value('sea_surface_water_wave__height')
array([ 3.5])

Available Models

The following table lists the models that are currently available through pymt.

Summary
Avulsion Avulsion dictates the movement of rivermouths along a coastline by modeling the changes of river channel angles through the floodplain as a stochastic random walk process.
Cem

The Coastline Evolution Model addresses predominately sandy, wave-dominated coastlines on time scales ranging from years to millenia and on spatial scales ranging from kilometers to hundreds of kilometers. CEM simulates planview coastline evolution due to wave-driven alongshore sediment transport. This model can incorporate river influence and transport fluvial sediment from one or more point sources along the coastline.

binder-Cem

Child

CHILD computes the time evolution of a topographic surface z(x,y,t) by fluvial and hillslope erosion and sediment transport.

binder-Child

ECSimpleSnow

ECSimpleSnow was orginally developed by Ross Brown and Bruce Brasnett in Environment Canada (EC). It is an empirical algorithm to melt snow according to the surface temperature and increase in snow depth according to the precipitation that has fallen since the last analysis time. It is a semi-empirical temperature index model. It provides a quick and acceptable answer when you only have very limited inputs. The one deficiency of the model is that it does not take account of the heat budget of the snowpack which means it will melt snow too quickly in the spring.

binder-ECSimpleSnow

ExponentialWeatherer Exponential weathering of bedrock on hillslopes. Uses exponential soil production function in the style of Ahnert (1976).
Flexure Simulate lithospheric flexure.
FlowAccumulator Component to accumulate flow and calculate drainage area. This is accomplished by first finding flow directions by a user-specified method and then calculating the drainage area and discharge. Optionally, spatially variable runoff can be set either by the model grid field ‘water__unit_flux_in’.
FlowDirectorD8 Single-path (steepest direction) flow direction finding on raster grids by the D8 method. This method considers flow on all eight links such that flow is possible on orthogonal and on diagonal links.
FlowDirectorDINF Directs flow by the D infinity method (Tarboton, 1997). Each node is assigned two flow directions, toward the two neighboring nodes that are on the steepest subtriangle. Partitioning of flow is done based on the aspect of the subtriangle.
FlowDirectorSteepest Find the steepest single-path steepest descent flow directions. It is equivalent to D4 method in the special case of a raster grid in that it does not consider diagonal links between nodes. For that capability, use FlowDirectorD8.
FlowRouter Single-path (steepest direction) flow routing, and calculates flow directions, drainage area, and (optionally) discharge.
FrostNumber

From Nelson and Outcalt (1987), the ‘frost number’, a dimensionless ratio defined by manipulation of either freezing and thawing degree-day sums or frost and thaw penetration depths, can be used to define an unambiguous latitudinal zonation of permafrost continuity. The index is computed using several variables influencing the depth of frost and thaw penetration, and can be related mathematically to the existence and continuity of permafrost. Although the frost number is a useful device for portraying the distribution of contemporary permafrost at continental scales, it is not capable of detecting relict permafrost and should not be mapped over small areas unless numerous climate stations are located in the region of interest.

binder-FrostNumber

GIPL

GIPL (Geophysical Institute Permafrost Laboratory) is an implicit finite difference one-dimensional heat flow numerical model. The model uses a fine vertical resolution grid which preserves the latent-heat effects in the phase transition zone, even under conditions of rapid or abrupt changes in the temperature fields. It includes upper boundary condition (usually air temperature), constant geothermal heat flux at the lower boundary (typically from 500 to 1000 m) and initial temperature distribution with depth. The other inputs are precipitation, prescribed water content and thermal properties of the multilayered soil column. As an output the model produces temperature distributions at different depths, active layer thickness and calculates time of freeze up. The results include temperatures at different depths and active layer thickness, freeze-up days.

binder-GIPL

Hydrotrend

Climate-driven hydrological water balance and transport model that simulates water discharge and sediment load at a river outlet. HydroTrend simulates water and sediment fluxes at a daily timescale based on drainage basin characteristics and climate. HydroTrend can provide this river flux information to other components like CEM and Sedflux2D or Sedflux3D

binder-Hydrotrend

Ku

The Kudryavtsev et al. (1974), or Ku model, presents an approximate solution of the Stefan problem. The model provides a steady-state solution under the assumption of sinusoidal air temperature forcing. It considers snow, vegetation, and soil layers as thermal damping to variation of air temperature. The layer of soil is considered to be a homogeneous column with different thermal properties in the frozen and thawed states. The main outputs are annual maximum frozen/thaw depth and mean annual temperature at the top of permafrost (or at the base of the active layer). It can be applied over a wide variety of climatic conditions.

binder-Ku

LinearDiffuser 2D diffusion using an explicit finite-volume method.
OverlandFlow Simulate overland flow using de Almeida approximations. Landlab component that simulates overland flow using the de Almeida et al., 2012 approximations of the 1D shallow water equations to be used for 2D flood inundation modeling. This component calculates discharge, depth and shear stress after some precipitation event across any raster grid.
Plume Plume simulates the sediment transport and deposition of single-grain size sediment from a river mouth entering into a marine basin by creating a turbulent jet. The model calculates a steady-state hypopycnal plume as a result of river water and sediment discharge based on simplified advection-diffusion equations. The model allows for plume deflection due to systematic coastal currents or Coriolis force
Rafem The River Avulsion and Floodplain Evolution Model (RAFEM) is a cellular model that simulates river and floodplain morphodynamics over large space and timescales. Cell size is larger than the channel belt width, and natural levees, which maintain a bankfull elevation above the channel bed, exist within a river cell. The river course is determined using a steepest-descent methodology, and erosion and deposition along the river profile are modeled as a linear diffusive process. An avulsion occurs when the riverbed becomes super-elevated relative to the surrounding floodplain, but only if the new steepest-descent path to sea level is shorter than the prior river course. If the new path to sea level is not shorter, then a crevasse splay is deposited in the adjacent river cells. The model has been designed to couple with the Coastline Evolution Model through the CSDMS Basic Model Interface.
Sedflux3D

Sedflux3D is a basin filling stratigraphic model. Sedflux3d simulates long-term marine sediment transport and accumulation into a three-dimensional basin over time scales of tens of thousands of years. It simulates the dynamics of strata formation of continental margins based on distribution of river plumes and tectonics.

binder-Sedflux3D

SoilMoisture Landlab component that simulates root-zone average soil moisture at each cell using inputs of potential evapotranspiration, live leaf area index, and vegetation cover.
StreamPowerEroder A simple, explicit implementation of a stream power algorithm.
Subside

The model is used to simulate the lithospheric load changes as the model evolves. Depending upon how the load distribution develops, this flexure can result in the basin uplifting or subsiding (or both). The pattern of subsidence in time and space largely determines the gross geometry of time-bounded units because it controls the rate at which space is created for sedimentation.

binder-Subside

TransportLengthHillslopeDiffuser Hillslope diffusion component in the style of Carretier et al. (2016, ESurf), and Davy and Lague (2009)
Vegetation

Landlab component that simulates net primary productivity, biomass and leaf area index at each cell based on inputs of root-zone average soil moisture.

Zhou, X., Istanbulluoglu, E., & Vivoni, E. R. (2013). Modeling the ecohydrological role of aspect controlled radiation on tree grass shrub coexistence in a semiarid climate. Water Resources Research, 49(5), 2872-2895.

Waves

Generates a shallow-water wave climate for a longshore transport module based on a user-defined distribution.

binder-Waves

Examples

Here are some examples that demonstrate how to run models using pymt. The examples in the first list run only single models. While the models do not couple with other models, they may couple with external data sets. The examples in the second list show how multiple models can be coupled together by exchanging data.

If you would like to run these examples yourself, in addition to installing pymt, you will have to install Jupyter Notebook:

$ conda install notebook

If you encounter any problems when running these Notebooks, please visit us at the CSDMS Help Desk and explain what occurred.

Single Models

Model Notebook
Frost Number Model binder-frost_number
Kudryavtsev Model binder-ku
GIPL Model binder-GIPL
ECSimpleSnow Model binder-ECSnow
Coastline Evolution Model binder-cem
Hydrotrend binder-hydrotrend
Hydrotrend Ganges binder-hydrotrend_Ganges
Sedflux3D binder-sedflux3d
Flexural Subsidence binder-subside

Coupled Models

Models Notebook
Coastline Evolution Model + Waves binder-cem_and_waves
GIPL + ECSimpleSnow Models binder-GIPL_and_ECSnow

Glossary

A glossary of terms used with pymt. Because pymt is a Python package, more information on many of these terms can be found in the Python Glossary.

$
The default shell prompt.
>>>
The default Python prompt.
The Python prompt for interactively entering code in an indeted code block.
Anaconda
A Python distribution that includes libraries for scientific computing and a package manager. See https://www.anaconda.com/distribution for more information.
Basic Model Interface (BMI)
A set a functions that are used to interact with and control a model. See https://csdms.colorado.edu/wiki/BMI_Description for more information.
Community Surface Dynamics Modeling System (CSDMS)
CSDMS is an NSF-funded program that seeks to transform the science and practice of earth-surface dynamics modeling. For more information, visit https://csdms.colorado.edu.
class
A program that acts as a template for creating objects.
conda
The package manager for Anaconda. Also an informal name for an Anaconda installation.
conda-forge
A collection of community-built packages distributed by Anaconda. See https://conda-forge.org.
conda environment
A conda sub-installation that isolates a group of packages from the main conda installation. See also Conda environments.
configuration file
A file that contains information for setting up a model.
coupling
See model coupling.
data
Information held by an object.
import
The process of bringing code from a Python module into another module or into an interactive Python session.
instance
See object.
Matplotlib
A Python plotting library used in pymt. For more information, see https://matplotlib.org.
method
Programs that act upon the data of an object.
model
A computer program that attempts to describe a physical process with mathematical relationships that evolve over time and are solved numerically. For more information, see, for example, https://en.wikipedia.org/wiki/Numerical_modeling_(geology).
model configuration file
A file, usually in a text-based format, that lists the tunable parameters of a model and supplies their initial values.
model coupling
Models are coupled when they exchange inputs and outputs, often at the resolution of individual time steps. One-way coupling occurs when the outputs from one model are used as inputs to another model. Two-way coupling is when outputs from one model are used as inputs for another model, which in turn supplies its outputs to the first model as inputs, producing a feedback.
module
A file (with the .py extension) that contains Python code.
NumPy
A Python library that provides arrays. Outputs from pymt are NumPy arrays. See also http://www.numpy.org.
object
A variable that is a concrete example of a class. Objects have data and methods that act upon those data.
package
A directory of Python modules that contains a package definition file. Packages can be installed into a Python distribution and imported into a Python session. Packages may define subpackages, each with their own package definition file.
package definition file
A file named __init__.py that denotes a directory contains a Python package.
Standard Names
A semantic mediation technology developed at CSDMS for precisely matching variable names between models. For more information, see https://csdms.colorado.edu/wiki/CSDMS_Standard_Names.
tarball
An archive file that contains several other files, usually compressed.

API Reference

If you are looking for information on a specific function, class, or method, this part of the documentation is for you.

Developer Documentation

pymt

pymt package

Subpackages
pymt.bmi package
Submodules
pymt.bmi.bmi module
class pymt.bmi.bmi.BMI[source]

Bases: object

finalize()[source]
get_current_time()[source]
get_end_time()[source]
get_grid_connectivity(grid_id)[source]
get_grid_offset(grid_id)[source]
get_grid_rank(grid_id)[source]
get_grid_shape(grid_id)[source]
get_grid_spacing(grid_id)[source]
get_grid_x(grid_id)[source]
get_grid_y(grid_id)[source]
get_grid_z(grid_id)[source]
get_input_var_names()[source]
get_output_var_names()[source]
get_start_time()[source]
get_time_step()[source]
get_var_grid(var_name)[source]
get_var_type(var_name)[source]
get_var_units(var_name)[source]
initialize(filename)[source]
run(time)[source]
exception pymt.bmi.bmi.Error[source]

Bases: Exception

Base class for BMI exceptions

exception pymt.bmi.bmi.VarNameError(name)[source]

Bases: pymt.bmi.bmi.Error

Exception to indicate a bad input/output variable name

Module contents
pymt.cfunits package
Submodules
pymt.cfunits.units module
Module contents
pymt.cmd package
Submodules
pymt.cmd.cmt_config module
pymt.cmd.cmt_config.main()[source]
pymt.cmd.cmt_config.read_component_configuration(names, vars=None)[source]
class pymt.cmd.cmt_config.redirect(stdout=None, stderr=None)[source]

Bases: object

Module contents
pymt.component package
Submodules
pymt.component.component module

Examples

Create an instance of the AirPort component and run it. The go method will initialize the component, run it for its duration, and finalize it.

>>> from pymt.framework.services import register_component_classes
>>> register_component_classes(['pymt.testing.services.AirPort'])
>>> comp = Component('AirPort')
>>> comp.start_time
0.0
>>> comp.current_time
0.0
>>> comp.end_time
100.0
>>> comp.go() # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
{name: air_port, status: running, time: 1.0}
...
{name: air_port, status: running, time: 100.0}
>>> comp.current_time
100.0

If you try to create a new component with the same name, it will raise an exception. To create a new instance of the component, you have to give it a new name.

>>> comp = Component('AirPort') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ValueError: AirPort
>>> comp = Component('AirPort', name='air_port')
>>> comp.current_time
0.0

You can gain finer control over component execution with the initialize, run, and finalize methods.

>>> comp.initialize()
>>> comp.run(10.) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
{name: air_port, status: running, time: 1.0}
...
{name: air_port, status: running, time: 10.0}
>>> comp.current_time
10.0
>>> comp.run(101.) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ValueError: AirPort
>>> comp.current_time
10.0
>>> comp.run(100.) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
{name: air_port, status: running, time: 11.0}
...
{name: air_port, status: running, time: 100.0}
>>> comp.current_time
100.0
>>> comp.finalize()
class pymt.component.component.Component(port, uses=None, provides=None, events=(), argv=(), time_step=1.0, run_dir='.', name=None)[source]

Bases: pymt.component.grid.GridMixIn

Wrap a BMI object as a component.

Use the Component class to wrap an object that exposes a BMI so that it can operate within the model-coupling framework.

Parameters:
  • port (str or port-like) – Name of the port to wrap or a Port instance.
  • uses (list, optional) – List of uses port names.
  • provides (list, optional) – List of provides port names.
  • argv (tuple, optional) – List of command line argument used to initialize the component.
  • time_step (float, optional) – Time interval over which component will run uses ports.
  • run_dir (str, optional) – Directory where the component will run.
connect(uses, port, vars_to_map=())[source]

Connect a uses port to a provides port.

Parameters:
  • uses (str) – Name of the uses port.
  • port (port-like) – Port-like object to connect to.
  • var_to_map (iterable, optional) – Names of variables to map.
current_time

Current time for component updating.

end_time

End time for component updating.

finalize()[source]

Finalize a component and any connected events.

classmethod from_dict(d)[source]

Create a Component instance from a dictionary.

Use configuration paramters from a dict-like object to create a new Component. The dictionary must contain the following keys: * name * class * initialize_args * time_step * run_dir

Parameters:d (dict-like) – Configuration parameters for the component.
Returns:A newly-created Component instance.
Return type:Component
classmethod from_path(path)[source]

Create a component from a file.

Parameters:path (str) – Path to yaml file.
Returns:A newly-created component.
Return type:Component
classmethod from_string(source)[source]

Deprecated.

Note

Deprecated. Use load() instead.

Create a component from a string.

Parameters:source (str) – Contents of a yaml file.
Returns:A newly-created component.
Return type:Component
go(stop=None)[source]

Run a component from start to end.

Run a component starting from its start time and ending at its stop time. The component and any attached ports are first initialized, then updated until the end time and, finally, their finalize methods are called.

Parameters:stop (float, optional) – Stop time, or None to run until end_time.
initialize()[source]

Initialize a component and any connected events.

classmethod load(source)[source]

Create a Component from a string.

This is an alternate constructor that create a component using values from a yaml-formatted string.

Parameters:source (str) – Yaml-formatted string.
Returns:A newly-created component.
Return type:Component
classmethod load_all(source)[source]

Create multiple components from a string.

This is an alternate constructor that creates a series of components using values from a yaml-formatted string.

Parameters:source (str) – Yaml-formatted string.
Returns:A list of newly-created component.
Return type:List of Components
provides

Names of connected provides ports.

register(name)[source]

Register component with the framework.

Associate name with the component instance withing the framework.

Parameters:name (str) – Name to associate component with.
run(stop_time)[source]

Run a component and any connect events.

Parameters:stop_time (float) – Time to run the component until.
start_time

Start time for component updating.

time_step

Component time step.

Time step over which a component will update any connected uses ports.

uses

Names of connected uses ports.

pymt.component.component.clip_stop_time(stop, stop_min, stop_max)[source]

Clip time between two values.

Clip a stopping time between two values. This is the same as the numpy clip function except that if stop is None then stop_max is returned.

Parameters:
  • stop (float) – Stop time.
  • stop_min (float) – Minimum stop time
  • stop_max (float) – Maximum stop time
Returns:

The, possibly clipped, stop time.

Return type:

float

Examples

>>> clip_stop_time(1., 0, 2.)
1.0
>>> clip_stop_time(1., 2, 3)
2.0
>>> clip_stop_time(4., 2, 3)
3.0
>>> clip_stop_time(None, 0, 1)
1.0
pymt.component.grid module
class pymt.component.grid.GridMixIn[source]

Bases: object

Mix-in that makes a Component grid-like.

Examples

>>> class Port(object):
...     def get_component_name(self):
...         return 'test-component'
...     def get_input_item_count(self):
...         return 1
...     def get_input_item_list(self):
...         return ['invar']
...     def get_output_item_count(self):
...         return 1
...     def get_output_item_list(self):
...         return ['outvar']
...     def get_grid_shape(self, grid_id):
...         return (2, 3)
...     def get_grid_spacing(self, grid_id):
...         return (2., 1.)
...     def get_grid_origin(self, grid_id):
...         return (0., 0.)
>>> from pymt.component.grid import GridMixIn
>>> class Component(GridMixIn):
...     def __init__(self):
...         self._port = Port()
...         super(Component, self).__init__()
>>> c = Component()
>>> c.name
'test-component'
>>> c.input_items
['invar']
>>> c.output_items
['outvar']
>>> c.get_grid_type(0)
'RASTER'
>>> c.get_x(0)
array([[ 0.,  1.,  2.],
       [ 0.,  1.,  2.]])
>>> c.get_y(0)
array([[ 0.,  0.,  0.],
       [ 2.,  2.,  2.]])
get_connectivity(grid_id)[source]
get_grid_type(grid_id)[source]

The type of the grid.

Parameters:grid_id (int) – Grid identifier.
Returns:type – The type of the grid.
Return type:str
get_offset(grid_id)[source]
get_value(*args, **kwds)[source]
get_var_units(name)[source]
get_x(grid_id)[source]
get_y(grid_id)[source]
get_z(grid_id)[source]
input_items

Input item names as a list.

name

Name of the wrapped component.

output_items

Output item names as a list.

set_value(name, values)[source]
pymt.component.grid.get_raster_node_coordinates(grid, grid_id)[source]

Get coordinates of nodes on a raster grid.

Parameters:
  • grid (grid_like) – A raster grid.
  • grid_id (int) – Grid identifier.
Returns:

coords – Coordinates of the grid nodes.

Return type:

ndarray

Examples

>>> from pymt.component.grid import get_raster_node_coordinates
>>> class RasterGrid(object):
...     def get_grid_shape(self, grid_id):
...         return (2, 3)
...     def get_grid_spacing(self, grid_id):
...         return (1., 2.)
...     def get_grid_origin(self, grid_id):
...         return (2., 1.)
>>> g = RasterGrid()
>>> (y, x) = get_raster_node_coordinates(g, 0)
>>> y
array([[ 2.,  2.,  2.],
       [ 3.,  3.,  3.]])
>>> x
array([[ 1.,  3.,  5.],
       [ 1.,  3.,  5.]])
pymt.component.grid.get_rectilinear_node_coordinates(grid, grid_id)[source]

Get coordinates of nodes on a rectilinear grid.

Parameters:
  • grid (grid_like) – A rectilinear grid.
  • grid_id (int) – Grid identifier.
Returns:

coords – Coordinates of the grid nodes.

Return type:

ndarray

Examples

>>> from pymt.component.grid import get_rectilinear_node_coordinates
>>> class RectilinearGrid(object):
...     def get_grid_x(self, grid_id):
...         return (0., 3., 4)
...     def get_grid_y(self, grid_id):
...         return (2., 7.)
>>> g = RectilinearGrid()
>>> (y, x) = get_rectilinear_node_coordinates(g, 0)
>>> y
array([[ 2.,  2.,  2.],
       [ 7.,  7.,  7.]])
>>> x
array([[ 0.,  3.,  4.],
       [ 0.,  3.,  4.]])
pymt.component.grid.get_structured_node_connectivity(grid, grid_id)[source]

Get cell connectivity on a structured grid of quadrilaterals.

Parameters:
  • grid (grid_like) – A structured grid.
  • grid_id (int) – Grid identifier.
Returns:

conn – Connectivities of nodes to cells.

Return type:

ndarray

Examples

>>> from pymt.component.grid import get_structured_node_connectivity
>>> class StructuredGrid(object):
...     def get_grid_shape(self, grid_id):
...         return (2, 3)
>>> g = StructuredGrid()
>>> (c, o) = get_structured_node_connectivity(g, 0)
>>> c
array([0, 1, 4, 3, 1, 2, 5, 4])
>>> o
array([4, 8])
pymt.component.grid.get_structured_node_coordinates(grid, grid_id)[source]

Get coordinates of nodes on a structured grid.

Parameters:
  • grid (grid_like) – A structured grid.
  • grid_id (int) – Grid identifier.
Returns:

coords – Coordinates of the grid nodes.

Return type:

ndarray

Examples

>>> from pymt.component.grid import get_structured_node_coordinates
>>> class StructuredGrid(object):
...     def get_grid_x(self, grid_id):
...         return np.array((0., 3., 4, 0., 3., 4.)).reshape((2, 3))
...     def get_grid_y(self, grid_id):
...         return np.array((2., 2., 2., 7., 7., 7.)).reshape((2, 3))
...     def get_grid_z(self, grid_id):
...         raise NotImplementedError('get_grid_z')
>>> g = StructuredGrid()
>>> (y, x) = get_structured_node_coordinates(g, 0)
>>> y
array([[ 2.,  2.,  2.],
       [ 7.,  7.,  7.]])
>>> x
array([[ 0.,  3.,  4.],
       [ 0.,  3.,  4.]])
pymt.component.grid.raster_node_coordinates(shape, spacing=None, origin=None)[source]

Node coordinates of a uniform rectilinear grid.

Parameters:
  • shape (array_like) – Size of grid in each dimension.
  • spacing (array_like (optional)) – Node spacing in each dimension (default is unit spacing).
  • origin (array_like (optional)) – Coordinates of the origin node (default is 0.0).
Returns:

coords – Node coordinates.

Return type:

ndarray

Examples

>>> from pymt.component.grid import raster_node_coordinates
>>> (y, x) = raster_node_coordinates((2, 3))
>>> y
array([[ 0.,  0.,  0.],
       [ 1.,  1.,  1.]])
>>> x
array([[ 0.,  1.,  2.],
       [ 0.,  1.,  2.]])
>>> (x, ) = raster_node_coordinates((3, ), (2., ), (1., ))
>>> x
array([ 1.,  3.,  5.])
pymt.component.model module
class pymt.component.model.Model(components, driver=None, duration=0.0)[source]

Bases: object

components

Names of the components.

driver

Name of the driver component.

duration

Length of time the model will run.

classmethod from_file(filename)[source]

Construct a Model from the contents of a file.

Parameters:filename (str) – Name of the model configuration file.
Returns:model – A newly-created model.
Return type:Model
classmethod from_file_like(file_like)[source]

Construct a Model from the contents of a file-like object.

Parameters:file_like (file_like) – A file-like object that contains the model configuration.
Returns:model – A newly-created model.
Return type:Model
classmethod from_string(contents)[source]

Construct a Model from a string.

Parameters:contents (str) – A string that contains the model configuration.
Returns:model – A newly-created model.
Return type:Model
go(filename=None)[source]

Start the model.

classmethod load(source)[source]

Construct a model from a YAML-formatted string.

Parameters:source (str or file_like) – YAML-formatted model configuration.
Returns:model – A newly-created Model.
Return type:Model

Examples

>>> from pymt.framework.services import del_component_instances
>>> del_component_instances(['air_port'])
>>> from pymt.component.model import Model
>>> source = '''
... name: air_port
... class: AirPort
... connectivity: []
... '''
>>> model = Model.load(source)
>>> model.components
['air_port']
>>> model.driver is None
True
>>> model.duration
0.0
>>> model.driver = 'air_port'
>>> model.duration = 1.
>>> model['air_port'].current_time
0.0
>>> model.go() # doctest: +NORMALIZE_WHITESPACE
{name: air_port, status: running, time: 1.0}
>>> model['air_port'].current_time
1.0
static load_components(source, with_connectivities=False)[source]

Construct a list of model components from a string.

Parameters:
  • source (str or file_like) – YAML-formatted components configuration.
  • with_connectivities (boolean (optional)) – Return connectivity dictionary along with components.
Returns:

components – Dictionary of newly-created components.

Return type:

dict

Examples

>>> from pymt.framework.services import del_component_instances
>>> del_component_instances(['air_port'])
>>> from pymt.component.model import Model
>>> source = '''
... name: air_port
... class: AirPort
... connectivity: []
... '''
>>> components = Model.load_components(source)
>>> list(components.keys())
['air_port']
pymt.component.model.get_exchange_item_mapping(items)[source]

Construct a mapping for exchange items.

Parameters:items (iterable) – List of exchange item names or (dest, src) tuples.
Returns:items – List of (dest, src) tuples of name mappings.
Return type:list

Examples

>>> from pymt.component.model import get_exchange_item_mapping
>>> get_exchange_item_mapping([('foo', 'bar'), 'baz'])
[('foo', 'bar'), ('baz', 'baz')]
>>> get_exchange_item_mapping([dict(source='bar',
...                                 destination='foo'), 'baz'])
[('foo', 'bar'), ('baz', 'baz')]
Module contents
pymt.events package
Submodules
pymt.events.chain module
class pymt.events.chain.ChainEvent(events)[source]

Bases: object

finalize()[source]
initialize()[source]
run(stop_time)[source]
update(stop_time)[source]
pymt.events.empty module

An empty event.

PassEvent implements an event-like interface but doesn’t do anything. This can be a useful event to give to an EventManager if you want to force the manager to stop at particular intervals.

class pymt.events.empty.PassEvent[source]

Bases: object

An event that doesn’t do anything.

finalize(stop_time)[source]
initialize()[source]
run(stop_time)[source]
pymt.events.manager module

Manage the execution of events on a timeline.

The EventManager puts events on a Timeline and then orchestrates the setup, execution, and teardown of the events as the time line advances. Events are classes that implement an event interface. That is, they implement the following methods:

  • initialize()
  • run(time)
  • finalize()

Because the EventManager class itself is event-like, it is able to manage other EventManager instances and even handle recursive events.

Examples

Create an event that prints, “hello”.

>>> class PrintHello(object):
...     def initialize(self):
...         print("hello from initialize")
...     def run(self, time):
...         print("hello!")
...     def finalize(self):
...         print("hello from finalize")

Add an instance of the event to be run at a regular interval to the manager.

>>> mngr = EventManager([(PrintHello(), 2.)])
>>> mngr.initialize()
hello from initialize
>>> mngr.run(1.)
>>> mngr.run(2.)
hello!
>>> mngr.finalize()
hello from finalize

You can also use an EventManager as a context,

>>> with EventManager([(PrintHello(), 2.)]) as mngr:
...     mngr.run(4.)
hello from initialize
hello!
hello!
hello from finalize
class pymt.events.manager.EventManager(*args)[source]

Bases: object

Parameters:events (dict-like) – Events as event-object/repeat interval pairs.

Examples

Create an EventManager without any events.

>>> mngr = EventManager()
>>> mngr.time
0.0
>>> len(mngr)
0

Create a manager with one recurring event.

>>> from pymt.events.empty import PassEvent
>>> mngr = EventManager([(PassEvent(), 1.)])
>>> len(mngr)
1

Create a manager with two recurring events.

>>> mngr = EventManager([(PassEvent(), 1.), (PassEvent(), 2.)])
>>> len(mngr)
2
add_recurring_event(event, interval)[source]

Add a managed event.

Add event to the list of managed events and run it with the recurrence interval, interval.

Parameters:
  • event (event-like) – Event to be managed.
  • interval (float) – Recurrence interval for the event.
finalize()[source]

Finalize managed events.

Execute the finalize method for each of the events being managed. Events are finalized in the reverse order in which they were initialized, and only if the manager has not yet been initialized.

classmethod from_path(path, prefix='')[source]

Create an EventManager from a file.

Parameters:
  • path (str) – Path to ini-formatted file.
  • prefix (str) – Prefix for section.
Returns:

A newly-created EventManager.

Return type:

EventManager

See also

from_string()
Alternate constructor that uses a string.
classmethod from_string(source, prefix='')[source]

Create an EventManager from a string.

Parameters:
  • source (str) – Ini-formatted string.
  • prefix (str) – Prefix for section.
Returns:

A newly-created EventManager.

Return type:

EventManager

See also

from_path()
Alternate constructor that uses a path name.
initialize()[source]

Initialize the managed events.

Execute the initialize methods of each of the events that are being managed, making sure the manager is not initialized if it is already in the initialization process. Events are initialized in the order they were given at creation.

run(stop_time)[source]

Run events until some time.

Execute the run method of each of the events being managed until stop_time is reached on the time line.

Parameters:stop_time (float) – Time to run events until.
time

Current time along the time line.

pymt.events.port module

Wrap a port as a Timeline event.

class pymt.events.port.PortEvent(*args, **kwds)[source]

Bases: pymt.component.grid.GridMixIn

Wrap a port as an event.

Parameters:
  • port (str) – Name of port.
  • init_args (list, optional) – List of arguments to initialize port.
  • run_dir (str, optional) – Path to directory to execute port.
finalize()[source]

Finalize the event.

Run the finalize method of the underlying port.

initialize()[source]

Initialize the event.

Run the underlying port’s initialization method in its run_dir. The event’s init_args are passed to the initialize method as arguments.

run(time)[source]

Run the event.

Call the run method of the underlying port using time as the run time.

Parameters:time (float) – Time to run the event to.
update(time)[source]
class pymt.events.port.PortMapEvent(*args, **kwds)[source]

Bases: object

An event that maps values between ports.

Parameters:
  • src_port (str) – Port name that is the data source.
  • dst_port (str) – Port name that is the destination.
  • vars_to_map (list, optional) – Names of variable to map.
  • method ({'direct', 'nearest'}, optional) – Method used to map values.
finalize()[source]
initialize()[source]

Initialize the data mappers.

run(stop_time)[source]

Map values from one port to another.

pymt.events.printer module
class pymt.events.printer.PrintEvent(*args, **kwds)[source]

Bases: object

finalize()[source]
initialize(*args)[source]
run(time)[source]
Module contents
pymt.framework package
Submodules
pymt.framework.bmi_bridge module
pymt.framework.bmi_docstring module
pymt.framework.bmi_mapper module
class pymt.framework.bmi_mapper.GridMapperMixIn[source]

Bases: object

map_to(name, **kwds)[source]

Map values to another grid.

Parameters:name (str) – Name of values to push.
map_value(name, **kwds)[source]

Map values from another grid.

Parameters:
  • name (str) – Name of values to map to.
  • mapfrom (tuple or bmi_like, optional) – BMI object from which values are mapped from. This can also be a tuple of (name, bmi), where name is the variable of the source grid and bmi is the bmi-like source. If not provided, use self.
  • nomap (narray of bool, optional) – Values in the destination grid to not map.
regrid(name, **kwds)[source]

Regrid values from one grid to another.

Parameters:
  • name (str) – Name of the values to regrid.
  • to (bmi_like, optional) – BMI object onto which to map values. If not provided, map values onto one of the object’s own grids.
  • to_name (str, optional) – Name of the value to map onto. If not provided, use name.
Returns:

The regridded values.

Return type:

ndarray

set_value(name, *args, **kwds)[source]

Set values for a variable. set_value(name, value) set_value(name, mapfrom=self, nomap=None)

Parameters:name (str) – Name of the destination values.
pymt.framework.bmi_mapper.as_esmf_field(mesh, field_name, data=None, at='node')[source]
pymt.framework.bmi_mapper.as_esmf_mesh(xy_of_node, nodes_at_patch=None, nodes_per_patch=None)[source]
pymt.framework.bmi_mapper.bmi_as_esmf_mesh(bmi_grid)[source]
pymt.framework.bmi_mapper.graph_as_esmf(graph, field_name, data=None, at='node')[source]
pymt.framework.bmi_mapper.ravel_jaggedarray(array)[source]
pymt.framework.bmi_mapper.run_regridding(source_field, destination_field, method=ESMP_REGRIDMETHOD_CONSERVE, unmapped=ESMP_UNMAPPEDACTION_ERROR)[source]
PRECONDITIONS:
Two ESMP_Fields have been created and a regridding operation is desired from ‘srcfield’ to ‘dstfield’.
POSTCONDITIONS:
An ESMP regridding operation has set the data on ‘dstfield’.
pymt.framework.bmi_metadata module

Incorporate CSDMS Model Metadata into PyMT.

PyMT uses the CSDMS model_metadata package, to incorporate CSDMS Model Metadata into BMI-enabled components when they are imported into PyMT. This ensures that:

  • Idenitying model information stays with the component as it appears within the CSDMS Modeling Framework. This ensures that the original author of the model is given appropriate credit and not forgotten in the wrapping of their model. In addition, a citation(s) is clearly displayed for the model. This ensures that a user running the model, either through PyMT or otherwise, will properly cite the original work that describes to model when publishing results that use the model.
  • Model input parameters are properly validated and model input files are properly constructed when preparing a model simulation.
exception pymt.framework.bmi_metadata.MetadataNotFoundError(path_to_metadata)[source]

Bases: Exception

pymt.framework.bmi_metadata.bmi_data_dir(name)[source]

Get a component’s data dir.

Parameters:name (str) – The name of the component.
Returns:The absolute path to the data directory for the component.
Return type:str
pymt.framework.bmi_metadata.find_model_metadata(plugin)[source]

Find the path to a plugin’s metadata.

Parameters:plugin (PyMT plugin) – A PyMT plugin object.
Returns:Path to the folder that contains the plugin’s metadata.
Return type:str
pymt.framework.bmi_plot module
pymt.framework.bmi_plot.quick_plot(bmi, name, **kwds)[source]
pymt.framework.bmi_setup module
class pymt.framework.bmi_setup.GitHubSetupMixIn[source]

Bases: object

setup(case='default', name=None, path=None)[source]
class pymt.framework.bmi_setup.SetupMixIn[source]

Bases: object

author
cite_as
contact
datadir
defaults
doi
email
license
parameters
setup(*args, **kwds)[source]

Set up a simulation.

Parameters:path (str, optional) – Path to a folder to set up the simulation. If not given, use a temporary folder.
Returns:Path to the folder that contains the set up simulation.
Return type:str
summary
url
version
pymt.framework.bmi_setup.fetch_input(name, path=None)[source]

Fetch input for a BMI component.

Parameters:
  • name (str) – Component name.
  • path (str, optional) – Directory to extract into.
Returns:

Path to input files for various cases.

Return type:

str

pymt.framework.bmi_setup.get_initialize_arg(dir_)[source]

Get the BMI initialize argument for a set of input files.

Parameters:dir (str) – Path to a folder that contains input files.
Returns:Argument that can be passed to a BMI initialize method.
Return type:str
pymt.framework.bmi_setup.url_to_input_file_repo(name)[source]

URL to a repo of input files for a component.

Parameters:name (str) – Component name.
Returns:URL of input-file repository.
Return type:str
pymt.framework.bmi_setup.url_to_input_file_zip(name)[source]

URL of zip file on input files.

Parameters:name (str) – Component name.
Returns:URL of zip file of input files.
Return type:str
pymt.framework.bmi_timeinterp module
class pymt.framework.bmi_timeinterp.BmiTimeInterpolator(*args, **kwds)[source]

Bases: object

add_data()[source]
interpolate(name, at)[source]
reset(method='linear')[source]
update_until(then, method=None, units=None)[source]
pymt.framework.bmi_ugrid module
pymt.framework.bmi_ugrid.coordinate_names(rank)[source]
pymt.framework.bmi_ugrid.dataset_from_bmi_grid(bmi, grid_id)[source]
pymt.framework.bmi_ugrid.index_names(rank)[source]
pymt.framework.services module

Access to framework services.

pymt.framework.services.del_component_instance(name)[source]

Remove an instance by name.

Parameters:name (str) – Component instance.
pymt.framework.services.del_component_instances(names)[source]

Remove a list of instances by name.

Parameters:names (list) – Component instance names.
pymt.framework.services.del_services()[source]
pymt.framework.services.get_component_class(name)[source]

Get a registered component class by name.

Parameters:name (str) – Name of the registered class.
Returns:The registered class.
Return type:class
Raises:KeyError – If the name is not registered with the framework.
pymt.framework.services.get_component_instance(name)[source]

Get a registered instance from the framework.

Parameters:name (str) – Name of the registered instance.
Returns:The registered instance.
Return type:object
Raises:KeyError – If name is not registered with the framework.
pymt.framework.services.get_component_instance_names()[source]

Names of all instances.

Returns:Names of all the instanciated components.
Return type:list
pymt.framework.services.instantiate_component(cls_name, instance_name)[source]

Instantiate a registered component class.

Instantiate a registered class and register that instance with the framework as instance_name.

Parameters:
  • cls_name (str) – Name of the registered class.
  • instance_name (str) – Name of the new instance.
Returns:

An instance of the registered class.

Return type:

object

Examples

>>> from pymt.framework.services import (
...     del_services,
...     register_component_class,
...     instantiate_component,
...     get_component_instance
... )
>>> del_services()
>>> register_component_class('pymt.testing.services.AirPort')
>>> air_port = instantiate_component('AirPort', 'air_port')
>>> air_port is get_component_instance('air_port')
True
pymt.framework.services.register_component_class(name, if_exists='raise')[source]

Register a component with the framework.

Add the component class, name, to the list of framework services. The component name should be the fully-qualified name of a Python class.

Parameters:
  • name (str) – Name of component to register.
  • if_exists ({'raise', 'warn', 'pass', 'clobber'}, optional) – What to do if the class is already registered.
Raises:
  • ValueError – If the class is already registered with the framework.
  • ImportError – If there is a problem importing any part of name.

Notes

This function will try to import name as though it were a fully-qualified name of a Python class. That is, if name were foo.bar.Baz, try the following:

from foo.bar import Baz

Examples

>>> from pymt.framework.services import (
...     del_services,
...     register_component_class,
...     get_component_class
... )
>>> del_services()
>>> register_component_class('pymt.testing.services.AirPort')
>>> get_component_class('AirPort')
<class 'pymt.testing.services.AirPort'>

Raise an ImportError if the component class could not be loaded.

>>> register_component_class('pymt.testing.services.NotAClass') # doctest : +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ImportError: cannot import component NotAClass from pymt.testing.services
>>> register_component_class('pymt.not.a.module.AirPort') # doctest : +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ValueError: component class exists (AirPort)
pymt.framework.services.register_component_classes(components, **kwds)[source]

Register a list of components with the framework.

Parameters:
  • components (list) – Component names to register.
  • if_exists ({'raise', 'warn', 'pass', 'clobber'}, optional) – What to do if the class is already registered.

See also

register_component_class()
Register just a single component.
pymt.framework.services.register_component_instance(name, instance)[source]

Register a component instance with the framework.

Parameters:
  • name (str) – Name of the component instance.
  • instance (object) – Component instance.
Raises:

ValueError – If name is already registered with the framework.

Examples

>>> from pymt.framework.services import (
...     del_services,
...     register_component_class,
...     get_component_instance
... )
>>> del_services()
>>> from pymt.testing.services import AirPort
>>> air_port = AirPort()
>>> register_component_instance('air_port', air_port)
>>> air_port is get_component_instance('air_port')
True
pymt.framework.timeinterp module
class pymt.framework.timeinterp.TimeInterpolator(data=(), method='linear', fill_value='extrapolate', maxsize=None)[source]

Bases: object

METHODS = ('linear', 'nearest', 'zero', 'slinear', 'quadratic', 'cubic', 'previous', 'next')
__call__(time)[source]

Interpolate the data at a given time.

__init__(data=(), method='linear', fill_value='extrapolate', maxsize=None)[source]

Interpolate data based on an evolving time series of data values.

Parameters:
  • data (iterable of (time, data), optional) – The data to use for the interpolation as an iterable of (time, data). data can either be scalars or numpy arrays.
  • method (str, optional) – The interpolation method to use.
  • fill_value (str or float, optional) – The value to use if trying to interpolate values that are outside the stored times. The default is to extrapolate to the given time.
  • maxsize (int, optional) – The maximum size of the buffer that holds the interpolation times. When the buffer reaches this size, the oldest times will be popped off a the stack.
add_data(time_and_data)[source]

Add new data points to the interpolator.

Parameters:
  • time (float or iterable of float) – Time values
  • data (float or iterable) – Data values to interpolate.
fill_value

Value to use when interpolating values outside of the data.

interpolate(time)[source]

Interpolate the data at a given time.

maxsize

The maximum number of times to be stored.

method

The method used for interpolating time.

Module contents
pymt.grids package
Submodules
pymt.grids.assertions module
pymt.grids.assertions.assert_is_rectilinear(grid, strict=True)[source]
pymt.grids.assertions.assert_is_structured(grid, strict=True)[source]
pymt.grids.assertions.assert_is_uniform_rectilinear(grid)[source]
pymt.grids.assertions.assert_is_unstructured(grid, strict=True)[source]
pymt.grids.assertions.is_callable_method(obj, method)[source]
pymt.grids.assertions.is_rectilinear(grid, strict=True)[source]
pymt.grids.assertions.is_structured(grid, strict=True)[source]
pymt.grids.assertions.is_uniform_rectilinear(grid)[source]
pymt.grids.assertions.is_unstructured(grid, strict=True)[source]
pymt.grids.connectivity module
>>> get_connectivity((6, ))
array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5])
>>> get_connectivity((6, ), ordering='ccw')
array([1, 0, 2, 1, 3, 2, 4, 3, 5, 4])
>>> get_connectivity((3, 4))
array([ 0,  1,  5,  4,  1,  2,  6,  5,  2,  3,  7,  6,  4,  5,  9,  8,  5,
        6, 10,  9,  6,  7, 11, 10])
>>> get_connectivity((3, 4), ordering='ccw')
array([ 1,  0,  4,  5,  2,  1,  5,  6,  3,  2,  6,  7,  5,  4,  8,  9,  6,
        5,  9, 10,  7,  6, 10, 11])
>>> shape = np.array([3, 4, 4])
>>> (c, o) = get_connectivity(shape, with_offsets=True)
>>> len(c) == (shape - 1).prod() * 8
True
>>> len(o) == (shape - 1).prod()
True
>>> np.all(np.diff(o) == 8)
True
>>> c[:o[0]]
array([ 0,  1,  5,  4, 16, 17, 21, 20])
>>> c[o[-2]:o[-1]]
array([26, 27, 31, 30, 42, 43, 47, 46])
>>> ids = get_connectivity((3, 4, 4), ordering='ccw')
>>> ids[:8]
array([ 1,  0,  4,  5, 17, 16, 20, 21])
>>> ids[-8:]
array([27, 26, 30, 31, 43, 42, 46, 47])
pymt.grids.connectivity.get_connectivity(shape, **kwds)[source]

Get the connectivity (and, optionally, offset) array for an ND structured grid. Elements will consist of two points for 1D grids, four points for 2D grids, eight points for 3D grids, etc. For a uniform rectilinear grid this would be lines, squares, and cubes.

The nodes of an element can be ordered either clockwise or counter-clockwise.

Parameters:
  • shape (tuple of int) – The shape of the grid.
  • ordering ({'cw', 'ccw', 'none'}, optional) – Node ordering. One of ‘cw’ (clockwise), ‘ccw’ (counter-clockwise), or ‘none’ (ordering not guaranteed).
  • dtype (str or numpy.dtype) – The desired data type of the returned arrays.
  • with_offsets (bool) – Return offset array along with connectivity
Returns:

Array of connectivities. If with_offsets keyword is True, return a tuple of (connectivity, offset).

Return type:

ndarray of int

Examples

A 1D grid with three points has 2 elements.

>>> get_connectivity ((3, ))
array([0, 1, 1, 2])
>>> get_connectivity ((3, ), ordering='ccw')
array([1, 0, 2, 1])

A 2D grid with 3 rows and 4 columns of nodes:

( 0 ) --- ( 1 ) --- ( 2 ) --- ( 3 )
  |         |         |         |
  |    0    |    1    |    2    |
  |         |         |         |
( 4 ) --- ( 5 ) --- ( 6 ) --- ( 7 )
  |         |         |         |
  |    3    |    4    |    5    |
  |         |         |         |
( 8 ) --- ( 9 ) --- ( 10) --- ( 11)
>>> get_connectivity((3, 4))
array([ 0,  1,  5,  4,  1,  2,  6,  5,  2,  3,  7,  6,  4,  5,  9,  8,  5,
        6, 10,  9,  6,  7, 11, 10])
>>> get_connectivity((3, 4), ordering='ccw')
array([ 1,  0,  4,  5,  2,  1,  5,  6,  3,  2,  6,  7,  5,  4,  8,  9,  6,
        5,  9, 10,  7,  6, 10, 11])

If ordering doesn’t matter, set ordering to ‘none’ as this could be slightly faster.

>>> (ids, offsets) = get_connectivity((3, 4), ordering='none', with_offsets=True)
>>> offsets
array([ 4,  8, 12, 16, 20, 24])
>>> ids
array([ 0,  1,  4,  5,  1,  2,  5,  6,  2,  3,  6,  7,  4,  5,  8,  9,  5,
        6,  9, 10,  6,  7, 10, 11])

Nodes connected to the first cell,

>>> ids[:offsets[0]]
array([0, 1, 4, 5])

Nodes connected to the second cell,

>>> ids[offsets[0]:offsets[1]]
array([1, 2, 5, 6])

Instead of using an offset array to indicate the end of each cell, you can return a list of connectivity arrays for each cell.

>>> shape = np.array((3, 4))
>>> ids = get_connectivity(shape, ordering='cw', as_cell_list=True)
>>> len(ids) == (shape - 1).prod()
True
>>> ids # doctest: +NORMALIZE_WHITESPACE
[array([0, 1, 5, 4]),
 array([1, 2, 6, 5]),
 array([2, 3, 7, 6]),
 array([4, 5, 9, 8]),
 array([ 5,  6, 10,  9]),
 array([ 6,  7, 11, 10])]
pymt.grids.connectivity.get_connectivity_1d(shape, ordering='cw', dtype=<class 'int'>)[source]
pymt.grids.connectivity.get_connectivity_2d(shape, ordering='cw', dtype=<class 'int'>)[source]

This is a little slower than the above and less general.

Examples

>>> get_connectivity_2d((3, 4))
array([ 0,  1,  5,  4,  1,  2,  6,  5,  2,  3,  7,  6,  4,  5,  9,  8,  5,
        6, 10,  9,  6,  7, 11, 10])
pymt.grids.esmp module

PyMT interface to ESMPy grids.

Examples

Create a grid that looks like this,

(3) --- (4) --- (5)
 |       |       |
 |   0   |   1   |
 |       |       |
(0) --- (1) --- (2)
>>> import ESMF
>>> mngr = ESMF.Manager()
>>> mngr.local_pet
0
>>> mngr.pet_count
1

Represent this grid as an unstructured grid.

>>> g = EsmpUnstructured([0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2],
...                      [0, 1, 4, 3, 1, 2, 5, 4], [4, 8], indexing='ij')
>>> g.get_point_count()
6
>>> g.get_cell_count()
2

As a structured grid,

>>> g = EsmpStructured([0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2], (2, 3),
...                    indexing='ij')
>>> g.get_point_count()
6
>>> g.get_cell_count()
2

As a uniform rectilinear (raster) grid,

>>> g = EsmpUniformRectilinear([2, 3], [1., 1.], [0., 0.])
>>> g.get_point_count()
6
>>> g.get_cell_count()
2

The as_mesh method provides a view of the grid as an ESMP_Mesh.

>>> mesh = g.as_mesh()
>>> mesh.node_count
6
>>> mesh.element_count
2

ESMF elements are the same as the grids cells. Likewise with nodes and points.

>>> g = EsmpRectilinear([0, 1], [0, 1, 2], indexing='ij')
>>> g.as_mesh().element_count == g.get_cell_count()
True
>>> g.as_mesh().node_count == g.get_point_count()
True

Uniform Rectilinear Field

Create a field on a grid that looks like this,

(3) --- (4) --- (5)
 |       |       |
 |   0   |   1   |
 |       |       |
(0) --- (1) --- (2)

Create the field,

>>> g = EsmpRasterField((2, 3), (1, 2), (0, 0), indexing='ij')
>>> g.get_cell_count()
2
>>> g.get_point_count()
6

Add some data at the points of our grid.

>>> data = np.arange(6)
>>> g.add_field('var0', data, centering='point')
>>> f = g.get_field('var0')
>>> f.data
array([ 0.,  1.,  2.,  3.,  4.,  5.])

The data can be given either as a 1D array or with the same shape as the point grid. In either case, though, it will be flattened.

>>> data = np.arange(6)
>>> data.shape = (2, 3)
>>> g.add_field('var0', data, centering='point')
>>> f = g.get_field('var0')
>>> f.data
array([ 0.,  1.,  2.,  3.,  4.,  5.])

If the size or shape doesn’t match, it’s an error.

>>> data = np.arange(2)
>>> g.add_field('bad var', data, centering='point') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
DimensionError: 2 != 6
>>> data = np.ones((3, 2))
>>> g.add_field ('bad var', data, centering='point') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
DimensionError: (3, 2) != (2, 3)

Map between two fields

>>> from pymt.grids.raster import UniformRectilinear
>>> from pymt.grids.rectilinear import Rectilinear
>>> src = EsmpRasterField((3,3), (1,1), (0, 0), indexing='ij')
>>> data = np.arange(src.get_cell_count(), dtype=np.float64)
>>> src.add_field('srcfield', data, centering='zonal')
>>> src.get_point_count()
9
>>> src.get_cell_count()
4
>>> src.get_x()
array([ 0.,  1.,  2.,  0.,  1.,  2.,  0.,  1.,  2.])
>>> src.get_y()
array([ 0.,  0.,  0.,  1.,  1.,  1.,  2.,  2.,  2.])
>>> src.get_connectivity() + 1
array([1, 2, 5, 4, 2, 3, 6, 5, 4, 5, 8, 7, 5, 6, 9, 8])
>>> dst = EsmpRectilinearField([0., .5, 1.5, 2.], [0., .5, 1.5, 2.])
>>> data = np.empty(dst.get_cell_count(), dtype=np.float64)
>>> dst.add_field('dstfield', data, centering='zonal')
>>> dst.get_point_count()
16
>>> dst.get_cell_count()
9
>>> dst.get_x()
array([ 0. ,  0.5,  1.5,  2. ,  0. ,  0.5,  1.5,  2. ,  0. ,  0.5,  1.5,
        2. ,  0. ,  0.5,  1.5,  2. ])
>>> dst.get_y()
array([ 0. ,  0. ,  0. ,  0. ,  0.5,  0.5,  0.5,  0.5,  1.5,  1.5,  1.5,
        1.5,  2. ,  2. ,  2. ,  2. ])
>>> dst.get_connectivity() + 1
array([ 1,  2,  6,  5,  2,  3,  7,  6,  3,  4,  8,  7,  5,  6, 10,  9,  6,
        7, 11, 10,  7,  8, 12, 11,  9, 10, 14, 13, 10, 11, 15, 14, 11, 12,
       16, 15])
>>> src_field = src.as_esmp('srcfield')
>>> dst_field = dst.as_esmp('dstfield')
>>> src.as_mesh().element_count
4
>>> src.as_mesh().node_count
9
>>> dst.as_mesh().element_count
9
>>> dst.as_mesh().node_count
16
>>> f = run_regridding(src_field, dst_field)
>>> f.data
array([ 0. ,  0.5,  1. ,  1. ,  1.5,  2. ,  2. ,  2.5,  3. ])

A bigger grid

>>> (M, N) = (300, 300)
>>> src = EsmpRasterField((M, N), (1, 1), (0, 0))

Map values on cells

>>> (X, Y) = np.meshgrid(np.arange (0.5, 299.5, 1.),
...                      np.arange (0.5, 299.5, 1.))
>>> data = np.sin(np.sqrt(X ** 2 + Y ** 2) * np.pi / M)
>>> src.add_field('srcfield', data, centering='zonal')
>>> dst = EsmpRasterField((M * 2 - 1, N * 2 - 1), (1. / 2, 1. / 2), (0, 0))
>>> data = np.empty(dst.get_cell_count(), dtype=np.float64)
>>> dst.add_field('dstfield', data, centering='zonal')
>>> src_field = src.as_esmp('srcfield')
>>> dst_field = dst.as_esmp('dstfield')
>>> f = run_regridding(src_field, dst_field)
>>> (X, Y) = np.meshgrid(np.arange (0.5, 299.5, .5),
...                      np.arange (0.5, 299.5, .5))
>>> exact = np.sin(np.sqrt(X ** 2 + Y ** 2) * np.pi / M)
>>> np.sum(np.abs(exact.flat - f.data))/(M * N * 4.) < 1e-2
True

Map values on points

>>> (X, Y) = np.meshgrid(np.arange(0.5, 300.5, 1.),
...                      np.arange(0.5, 300.5, 1.))
>>> data = np.sin(np.sqrt(X ** 2 + Y ** 2) * np.pi / M)
>>> src.add_field('srcfield_at_points', data, centering='point')
>>> data = np.empty(dst.get_point_count(), dtype=np.float64)
>>> dst.add_field('dstfield_at_points', data, centering='point')
>>> src_field = src.as_esmp('srcfield_at_points')
>>> dst_field = dst.as_esmp('dstfield_at_points')
>>> f = run_regridding(src_field, dst_field,
...                    method=ESMF.RegridMethod.BILINEAR)
>>> (X, Y) = np.meshgrid(np.arange(0.5, 300., .5), np.arange(0.5, 300., .5))
>>> exact = np.sin(np.sqrt (X ** 2 + Y ** 2) * np.pi / M)
>>> np.sum(np.abs(exact.flat - f.data))/(M * N * 4.) < 1e-5
True
class pymt.grids.esmp.EsmpField(*args, **kwargs)[source]

Bases: pymt.grids.igrid.IField

add_field(field_name, val, centering='zonal')[source]
as_esmp(field_name)[source]
get_cell_count()[source]
get_field(field_name)[source]

Return an array of values for the requested field

get_point_count()[source]
class pymt.grids.esmp.EsmpGrid[source]

Bases: pymt.grids.igrid.IGrid

as_mesh()[source]
get_cell_count()[source]
get_point_count()[source]
class pymt.grids.esmp.EsmpRasterField(shape, spacing, origin, **kwds)[source]

Bases: pymt.grids.esmp.EsmpUniformRectilinear, pymt.grids.esmp.EsmpRectilinearField

class pymt.grids.esmp.EsmpRectilinear(*args, **kwds)[source]

Bases: pymt.grids.rectilinear.Rectilinear, pymt.grids.esmp.EsmpGrid

name = 'ESMPRectilinear'
class pymt.grids.esmp.EsmpRectilinearField(*args, **kwds)[source]

Bases: pymt.grids.esmp.EsmpRectilinear, pymt.grids.esmp.EsmpStructuredField

class pymt.grids.esmp.EsmpStructured(*args, **kwds)[source]

Bases: pymt.grids.structured.Structured, pymt.grids.esmp.EsmpGrid

name = 'ESMPStructured'
class pymt.grids.esmp.EsmpStructuredField(*args, **kwds)[source]

Bases: pymt.grids.esmp.EsmpStructured, pymt.grids.esmp.EsmpField

add_field(field_name, val, centering='zonal')[source]
class pymt.grids.esmp.EsmpUniformRectilinear(shape, spacing, origin, **kwds)[source]

Bases: pymt.grids.raster.UniformRectilinear, pymt.grids.esmp.EsmpStructured

name = 'ESMPUniformRectilinear'
class pymt.grids.esmp.EsmpUnstructured(*args, **kwds)[source]

Bases: pymt.grids.unstructured.Unstructured, pymt.grids.esmp.EsmpGrid

name = 'ESMPUnstructured'
class pymt.grids.esmp.EsmpUnstructuredField(*args, **kwds)[source]

Bases: pymt.grids.esmp.EsmpUnstructured, pymt.grids.esmp.EsmpField

pymt.grids.esmp.run_regridding(source_field, destination_field, method=ESMP_REGRIDMETHOD_CONSERVE, unmapped=ESMP_UNMAPPEDACTION_ERROR)[source]
PRECONDITIONS:
Two ESMP_Fields have been created and a regridding operation is desired from ‘srcfield’ to ‘dstfield’.
POSTCONDITIONS:
An ESMP regridding operation has set the data on ‘dstfield’.
pymt.grids.field module
class pymt.grids.field.GridField(*args, **kwargs)[source]

Bases: pymt.grids.unstructured.Unstructured, pymt.grids.igrid.IField

add_field(field_name, val, centering='zonal', units='-', exist_action='clobber', time=None)[source]
get_cell_fields(*args)[source]
get_field(field_name)[source]

Return an array of values for the requested field

get_field_units(field_name)[source]
get_point_fields(*args)[source]
has_field(name)[source]
items()[source]
keys()[source]
pop_field(field_name, *args, **kwds)[source]
set_field_units(field_name, units)[source]
values()[source]
class pymt.grids.field.RasterField(shape, spacing, origin, **kwds)[source]

Bases: pymt.grids.raster.UniformRectilinear, pymt.grids.field.StructuredField

Create a field that looks like this,

(0) --- (1) --- (2)
 |       |       |
 |   0   |   1   |
 |       |       |
(3) --- (4) --- (5)

Create the field,

>>> g = RasterField ((2,3), (1,2), (0, 0), indexing='ij')
>>> g.get_cell_count ()
2
>>> g.get_point_count ()
6

Add some data at the points of our grid.

>>> data = np.arange (6)
>>> g.add_field ('var0', data, centering='point')
>>> g.get_field ('var0')
array([0, 1, 2, 3, 4, 5])

The data can be given either as a 1D array or with the same shape as the point grid. In either case, though, it will be flattened.

>>> data = np.arange (6)
>>> data.shape = (2, 3)
>>> g.add_field ('var0', data, centering='point')
>>> g.get_field ('var0')
array([0, 1, 2, 3, 4, 5])

If the size or shape doesn’t match, it’s an error.

>>> data = np.arange (2)
>>> g.add_field ('bad var', data, centering='point') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
DimensionError: 2 != 6
>>> data = np.ones ((3, 2))
>>> g.add_field ('bad var', data, centering='point') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
DimensionError: (3, 2) != (2, 3)

Add data to the cells of the grid. Again, the data can be given as a 1D array or with the same shape as the cell grid and if the size or shape doesn’t match raise an exception.

>>> data = np.arange (2)
>>> g.add_field('var1', data, centering='zonal')
>>> g.get_field('var1')
array([0, 1])
>>> data = np.ones((2, 1))
>>> g.add_field('bad var', data, centering='zonal') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
DimensionError: (2, 1) != (1, 2)
>>> data = np.arange(3)
>>> g.add_field('bad var', data, centering='zonal') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
DimensionError: 3 != 2
>>> data = np.array(3)
>>> g.add_field('bad var', data, centering='zonal')  # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
DimensionError: 1 != 2

A 1D-Field,

>>> g = RasterField ((6, ), (1.5, ), (0.5, ), indexing='ij')
>>> g.get_point_count ()
6
>>> g.get_cell_count ()
5
>>> point_data = np.arange (6.)
>>> g.add_field ('Point Data', point_data, centering='point')
>>> cell_data = np.arange (5.)*10.
>>> g.add_field ('Cell Data', cell_data, centering='zonal')
>>> g.get_field ('Cell Data')
array([  0.,  10.,  20.,  30.,  40.])
>>> g.get_field ('Point Data')
array([ 0.,  1.,  2.,  3.,  4.,  5.])

A 3D-Field,

>>> g = RasterField ((4, 3, 2), (1.5, 1., 3), (0.5, 0, -.5 ), indexing='ij')
>>> g.get_point_count ()
24
>>> g.get_cell_count ()
6
>>> g.add_field ('Point Data', g.get_x (), centering='point')
>>> cell_data = np.arange (6.)*10.
>>> g.add_field ('Cell Data', cell_data, centering='zonal')
>>> g.get_field ('Cell Data')
array([  0.,  10.,  20.,  30.,  40.,  50.])
>>> g.get_field('Point Data')
array([-0.5,  2.5, -0.5,  2.5, -0.5,  2.5, -0.5,  2.5, -0.5,  2.5, -0.5,
        2.5, -0.5,  2.5, -0.5,  2.5, -0.5,  2.5, -0.5,  2.5, -0.5,  2.5,
       -0.5,  2.5])
>>> g.get_shape()
array([4, 3, 2])
>>> g.get_x().size == g.get_field('Point Data').size
True
>>> x = g.get_x()
>>> x.shape
(24,)
>>> x.shape = g.get_shape()
>>> x.shape
(4, 3, 2)
class pymt.grids.field.RectilinearField(*args, **kwds)[source]

Bases: pymt.grids.rectilinear.Rectilinear, pymt.grids.field.StructuredField

class pymt.grids.field.StructuredField(*args, **kwds)[source]

Bases: pymt.grids.structured.Structured, pymt.grids.field.GridField

add_field(field_name, val, centering='zonal', units='-', exist_action='clobber', time=None)[source]
class pymt.grids.field.UnstructuredField(*args, **kwargs)[source]

Bases: pymt.grids.field.GridField

pymt.grids.field.combine_args_to_list(*args, **kwds)[source]
pymt.grids.grid_type module
class pymt.grids.grid_type.GridType[source]

Bases: object

class pymt.grids.grid_type.GridTypeRectilinear[source]

Bases: pymt.grids.grid_type.GridType

class pymt.grids.grid_type.GridTypeStructured[source]

Bases: pymt.grids.grid_type.GridType

class pymt.grids.grid_type.GridTypeUnstructured[source]

Bases: pymt.grids.grid_type.GridType

pymt.grids.igrid module
exception pymt.grids.igrid.CenteringValueError(val)[source]

Bases: pymt.grids.igrid.Error

Error to indicate an invalid value for value centering.

exception pymt.grids.igrid.DimensionError(dim0, dim1)[source]

Bases: pymt.grids.igrid.Error

Error to indicate a dimension mismatch when adding a value field to a grid.

exception pymt.grids.igrid.Error[source]

Bases: Exception

Base class for grid and field errors

exception pymt.grids.igrid.GridTypeError[source]

Bases: pymt.grids.igrid.Error

class pymt.grids.igrid.IField[source]

Bases: pymt.grids.igrid.IGrid

get_field(field_name)[source]

Return an array of values for the requested field

class pymt.grids.igrid.IGrid[source]

Bases: object

An interface for a grid object that represents a structured or unstructured grid of nodes and elements.

get_connectivity()[source]

Return the connectivity array for the grid.

get_offset()[source]

Return an array of offsets in to the connectivity array for each element of the grid.

get_x()[source]

Return the x-coordinates of the grid nodes.

get_y()[source]

Return the y-coordinates of the grid nodes.

exception pymt.grids.igrid.NonStructuredGridError[source]

Bases: pymt.grids.igrid.GridTypeError

Error to indicate a grid is not a structured grid

type = 'structured'
exception pymt.grids.igrid.NonUniformGridError[source]

Bases: pymt.grids.igrid.GridTypeError

Error to indicate a grid is not a uniform rectilinear grid

type = 'uniform rectilinear'
pymt.grids.map module

Examples

Rectilinear

Create a rectilinear grid that is 2x3:

(0) --- (1) --- (2)
 |       |       |
 |       |       |
 |  [0]  |  [1]  |
 |       |       |
 |       |       |
(3) --- (4) --- (5)

Numbers in parens are node IDs, and numbers in square brackets are cell IDs.

>>> g = RectilinearMap ([0, 2], [0, 1, 2])
>>> g.get_x ()
array([ 0.,  1.,  2.,  0.,  1.,  2.])
>>> g.get_y ()
array([ 0.,  0.,  0.,  2.,  2.,  2.])

Node 1 is shared by both cell 0, and 1; node 5 only is part of cell 1.

>>> g.get_shared_cells (1)
[0, 1]
>>> g.get_shared_cells (5)
[1]

Point (.5, 1.) is contained only within cell 0.

>>> g.is_in_cell (.5, 1., 0)
True
>>> g.is_in_cell (.5, 1., 1)
False

Point (1., 1.) is on a border and so is contained by both cells.

>>> g.is_in_cell (1, 1., 0)
True
>>> g.is_in_cell (1, 1., 1)
True
class pymt.grids.map.RectilinearMap(*args, **kwds)[source]

Bases: pymt.grids.rectilinear.Rectilinear, pymt.grids.map.UnstructuredMap

name = 'Rectilinear'
class pymt.grids.map.StructuredMap(*args, **kwds)[source]

Bases: pymt.grids.structured.Structured, pymt.grids.map.UnstructuredMap

name = 'Structured'
class pymt.grids.map.UniformRectilinearMap(shape, spacing, origin, **kwds)[source]

Bases: pymt.grids.raster.UniformRectilinear, pymt.grids.map.UnstructuredMap

name = 'UniformRectilinear'
class pymt.grids.map.UnstructuredMap(*args, **kwargs)[source]

Bases: pymt.grids.unstructured.Unstructured

get_shared_cells(point_id)[source]
Parameters:point_id (int) – ID of a point in the grid.
Returns:Indices to cells that share a given node.
Return type:ndarray of int
is_in_cell(x, y, cell_id)[source]

Check if a point is in a cell.

Parameters:
  • x (float) – x-coordinate of point to check.
  • y (float) – y-coordinate of point to check.
  • cell_id (int) – ID of the cell in the grid.
Returns:

True if the point (x, y) is contained in the cell.

Return type:

bool

name = 'Unstructured'
class pymt.grids.map.UnstructuredPointsMap(*args, **kwds)[source]

Bases: pymt.grids.unstructured.UnstructuredPoints

get_shared_cells(point_id)[source]
is_in_cell(x, y, cell_id)[source]
name = 'UnstructuredPoints'
pymt.grids.meshgrid module

Notes

This function supports both indexing conventions through the indexing keyword argument. Giving the string ‘ij’ returns a meshgrid with matrix indexing, while ‘xy’ returns a meshgrid with Cartesian indexing. In the 2-D case with inputs of length M and N, the outputs are of shape (N, M) for ‘xy’ indexing and (M, N) for ‘ij’ indexing. In the 3-D case with inputs of length M, N and P, outputs are of shape (N, M, P) for ‘xy’ indexing and (M, N, P) for ‘ij’ indexing. The difference is illustrated by the following code snippet:

xv, yv = meshgrid(x, y, sparse=False, indexing='ij')
for i in range(nx):
    for j in range(ny):
        # treat xv[i,j], yv[i,j]

xv, yv = meshgrid(x, y, sparse=False, indexing='xy')
for i in range(nx):
    for j in range(ny):
        # treat xv[j,i], yv[j,i]

See also

index_tricks.mgrid
Construct a multi-dimensional “meshgrid” using indexing notation.
index_tricks.ogrid
Construct an open multi-dimensional “meshgrid” using indexing notation.

Examples

>>> nx, ny = (3, 2)
>>> x = np.linspace(0, 1, nx)
>>> y = np.linspace(0, 1, ny)
>>> xv, yv = meshgrid(x, y)
>>> xv
array([[ 0. ,  0.5,  1. ],
       [ 0. ,  0.5,  1. ]])
>>> yv
array([[ 0.,  0.,  0.],
       [ 1.,  1.,  1.]])
>>> xv, yv = meshgrid(x, y, sparse=True)  # make sparse output arrays
>>> xv
array([[ 0. ,  0.5,  1. ]])
>>> yv
array([[ 0.],
       [ 1.]])

meshgrid is very useful to evaluate functions on a grid.

>>> x = np.arange(-5, 5, 0.1)
>>> y = np.arange(-5, 5, 0.1)
>>> xx, yy = meshgrid(x, y, sparse=True)
>>> z = np.sin(xx**2 + yy**2) / (xx**2 + yy**2)
pymt.grids.meshgrid.meshgrid(*xi, **kwargs)[source]

Coordinate matrices from two or more coordinate vectors.

Make N-D coordinate arrays for vectorized evaluations of N-D scalar/vector fields over N-D grids, given one-dimensional coordinate arrays x1, x2,…, xn.

Parameters:
  • xi (array_like) – 1-D arrays representing the coordinates of a grid.
  • indexing ({'xy', 'ij'}, optional) – Cartesian (‘xy’, default) or matrix (‘ij’) indexing of output. See Notes for more details.
  • sparse (bool, optional) – If True a sparse grid is returned in order to conserve memory. Default is False.
  • copy (bool, optional) – If False, a view into the original arrays are returned in order to conserve memory. Default is True. Please note that sparse=False, copy=False will likely return non-contiguous arrays. Furthermore, more than one element of a broadcast array may refer to a single memory location. If you need to write to the arrays, make copies first.
Returns:

For vectors x1, x2,…, ‘xn’ with lengths Ni=len(xi) , return (N1, N2, N3,...Nn) shaped arrays if indexing=’ij’ or (N2, N1, N3,...Nn) shaped arrays if indexing=’xy’ with the elements of xi repeated to fill the matrix along the first dimension for x1, the second for x2 and so on.

Return type:

ndarray

pymt.grids.raster module

Examples

Create a grid that consists of 2x3 nodes using ‘xy’ and ‘ij’ indexing.

ij-indexing

Create a grid of length 2 in the i direction, and 3 in the j direction.

>>> g = UniformRectilinear ((2,3), (1,2), (.5, 0), indexing='ij', units=('m', 'km'))
>>> g.get_x()
array([ 0.,  2.,  4.,  0.,  2.,  4.])
>>> g.get_y()
array([ 0.5,  0.5,  0.5,  1.5,  1.5,  1.5])
>>> [g.get_x_units(), g.get_y_units()]
['km', 'm']
>>> g.get_z_units()
Traceback (most recent call last):
        ...
IndexError: Dimension out of bounds
>>> [g.get_coordinate_units(i) for i in [0, 1]]
['m', 'km']
>>> g.get_coordinate_units(2)
Traceback (most recent call last):
        ...
IndexError: Dimension out of bounds
>>> g.get_shape()
array([2, 3])
>>> g.get_spacing()
array([ 1.,  2.])
>>> g.get_origin()
array([ 0.5,  0. ])
>>> g.get_offset()
array([4, 8])
>>> g.get_connectivity()
array([0, 1, 4, 3, 1, 2, 5, 4])

Uniform rectilinear grid of points

Create a grid of length 2 in the i direction, and 3 in the j direction.

>>> g = UniformRectilinearPoints ((2,3), (1,2), (.5, 0), indexing='ij', set_connectivity=True)
>>> g.get_x()
array([ 0.,  2.,  4.,  0.,  2.,  4.])
>>> g.get_y()
array([ 0.5,  0.5,  0.5,  1.5,  1.5,  1.5])
>>> g.get_shape()
array([2, 3])
>>> g.get_spacing()
array([ 1.,  2.])
>>> g.get_origin()
array([ 0.5,  0. ])
>>> g.get_point_count()
6
>>> g.get_cell_count()
0

The offset runs from 1 up to (and including) the number of points.

>>> all (g.get_offset ()==np.arange (1, g.get_point_count ()+1))
True

The connectivity runs from 0 to one less than the number of points.

>>> all (g.get_connectivity ()==np.arange (g.get_point_count ()))
True

1D-grid of points

>>> g = UniformRectilinearPoints ((5, ), (1., ), (.5,), indexing='ij', set_connectivity=True)
>>> g.get_x()
array([ 0.5,  1.5,  2.5,  3.5,  4.5])

3D-grid of cells

>>> g = UniformRectilinear ((4, 3, 2), (1, 2, 3), (-1, 0, 1), indexing='ij')
>>> g.get_x()
array([ 1.,  4.,  1.,  4.,  1.,  4.,  1.,  4.,  1.,  4.,  1.,  4.,  1.,
        4.,  1.,  4.,  1.,  4.,  1.,  4.,  1.,  4.,  1.,  4.])
>>> g.get_y()
array([ 0.,  0.,  2.,  2.,  4.,  4.,  0.,  0.,  2.,  2.,  4.,  4.,  0.,
        0.,  2.,  2.,  4.,  4.,  0.,  0.,  2.,  2.,  4.,  4.])
>>> g.get_z()
array([-1., -1., -1., -1., -1., -1.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,
        1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  2.,  2.,  2.])
class pymt.grids.raster.UniformRectilinear(shape, spacing, origin, **kwds)[source]

Bases: pymt.grids.raster.UniformRectilinearPoints, pymt.grids.rectilinear.Rectilinear

Create a rectilinear grid with uniform spacing in the x and y directions.

Parameters:
  • shape (tuple of int) – Grid shape measured in number of nodes.
  • spacing (tuple of int) – Spacing between nodes in each direction of a rectilinear grid.
  • origin (tuple of int) – Coordinates of the lower-left corner of the grid.
  • indexing ({'xy', 'ij'}, optional) – Cartesian (‘xy’, default) or matrix (‘ij’) indexing of output. See Notes for more details.
Returns:

An instance of a UniformRectilinear grid.

Return type:

UniformRectilinear

class pymt.grids.raster.UniformRectilinearPoints(shape, spacing, origin, **kwds)[source]

Bases: pymt.grids.rectilinear.RectilinearPoints

get_origin()[source]

Coordinates of the grid’s lower-left corner

get_spacing()[source]

Spacing between nodes in each direction

pymt.grids.rectilinear module

Examples

Create a grid of length 2 in the x direction, and 3 in the y direction.

>>> g = Rectilinear([1., 2., 3.], [1., 2., 4., 8.])
>>> g.get_point_count()
12
>>> g.get_cell_count()
6
>>> g.get_x()
array([ 1.,  2.,  4.,  8.,  1.,  2.,  4.,  8.,  1.,  2.,  4.,  8.])
>>> g.get_y()
array([ 1.,  1.,  1.,  1.,  2.,  2.,  2.,  2.,  3.,  3.,  3.,  3.])
>>> g.get_shape()
array([3, 4])

Create a grid of length 2 in the i direction, and 3 in the j direction.

>>> g = Rectilinear([1., 2., 4., 8.], [1., 2., 3.], indexing='ij')
>>> g.get_x()
array([ 1.,  2.,  3.,  1.,  2.,  3.,  1.,  2.,  3.,  1.,  2.,  3.])
>>> g.get_y()
array([ 1.,  1.,  1.,  2.,  2.,  2.,  4.,  4.,  4.,  8.,  8.,  8.])
>>> g.get_shape()
array([4, 3])
>>> g.get_offset()
array([ 4,  8, 12, 16, 20, 24])
>>> g.get_connectivity()
array([ 0,  1,  4,  3,  1,  2,  5,  4,  3,  4,  7,  6,  4,  5,  8,  7,  6,
        7, 10,  9,  7,  8, 11, 10])

Rectilinear grid of points

Create a grid of length 2 in the i direction, and 3 in the j direction.

>>> g = RectilinearPoints ([1., 2., 4., 8.], [1., 2., 3.], indexing='ij', set_connectivity=True)
>>> g.get_x()
array([ 1.,  2.,  3.,  1.,  2.,  3.,  1.,  2.,  3.,  1.,  2.,  3.])
>>> g.get_y()
array([ 1.,  1.,  1.,  2.,  2.,  2.,  4.,  4.,  4.,  8.,  8.,  8.])
>>> g.get_shape ()
array([4, 3])
>>> g.get_point_count()
12
>>> g.get_cell_count()
0

The offset runs from 1 up to (and including) the number of points.

>>> all (g.get_offset ()==np.arange (1, g.get_point_count ()+1))
True

The connectivity runs from 0 to one less than the number of points.

>>> all (g.get_connectivity ()==np.arange (g.get_point_count ()))
True

1D Rectilinear grid

>>> g = Rectilinear([1,3,4,5,6], set_connectivity=True)
>>> g.get_x()
array([ 1.,  3.,  4.,  5.,  6.])
>>> g.get_point_count()
5
>>> g.get_cell_count()
4
>>> g.get_connectivity()
array([0, 1, 1, 2, 2, 3, 3, 4])
>>> g.get_offset()
array([2, 4, 6, 8])

3D Rectilinear grid

>>> g = Rectilinear ([0, 1], [2, 3], set_connectivity=True, indexing='ij')
>>> g.get_x()
array([ 2.,  3.,  2.,  3.])
>>> g.get_y()
array([ 0.,  0.,  1.,  1.])
>>> g = Rectilinear ([0, 1], [2, 3], [4, 5], set_connectivity=True, indexing='ij')
>>> g.get_x()
array([ 4.,  5.,  4.,  5.,  4.,  5.,  4.,  5.])
>>> g.get_y()
array([ 2.,  2.,  3.,  3.,  2.,  2.,  3.,  3.])
>>> g.get_z()
array([ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.])
>>> g.get_point_count()
8
>>> g.get_cell_count()
1
>>> g = Rectilinear([0, 1, 2, 3], [4, 5, 6], [7, 8], set_connectivity=True, indexing='ij')
>>> g.get_x()
array([ 7.,  8.,  7.,  8.,  7.,  8.,  7.,  8.,  7.,  8.,  7.,  8.,  7.,
        8.,  7.,  8.,  7.,  8.,  7.,  8.,  7.,  8.,  7.,  8.])
>>> g.get_shape()
array([4, 3, 2])
>>> x = g.get_x()
>>> x.shape = g.get_shape()
class pymt.grids.rectilinear.Rectilinear(*args, **kwds)[source]

Bases: pymt.grids.rectilinear.RectilinearPoints, pymt.grids.structured.Structured

Create a rectilinear grid.

Parameters:
  • x (ndarray) – 1-D array of x-coordinates of nodes.
  • y (ndarray) – 1-D array of y-coordinates of nodes.
  • shape (tuple of int) – Grid shape measured in number of nodes
  • indexing ({'xy', 'ij'}, optional) – Cartesian (‘xy’, default) or matrix (‘ij’) indexing of output.
Returns:

An instance of a Rectilinear grid.

Return type:

Rectilinear

class pymt.grids.rectilinear.RectilinearPoints(*args, **kwds)[source]

Bases: pymt.grids.structured.StructuredPoints

get_axis_coordinates(axis=None, indexing='ij')[source]
get_x_coordinates()[source]

Examples

>>> g = Rectilinear([0, 1], [2, 3], [4, 5], set_connectivity=True, indexing='ij')
>>> g.get_x_coordinates()
array([ 4.,  5.])
get_xyz_coordinates()[source]
get_y_coordinates()[source]

Examples

>>> g = Rectilinear([0, 1], [2, 3], [4, 5], set_connectivity=True, indexing='ij')
>>> g.get_y_coordinates()
array([ 2.,  3.])
get_z_coordinates()[source]

Examples

>>> g = Rectilinear([0, 1], [2, 3], [4, 5], set_connectivity=True, indexing='ij')
>>> g.get_z_coordinates()
array([ 0.,  1.])
pymt.grids.structured module

Examples

Create a grid of length 2 in the x direction, and 3 in the y direction.

>>> (x, y) = np.meshgrid ([1., 2., 4., 8.], [1., 2., 3.])
>>> g = Structured(y.flatten(), x.flatten(), [3, 4])
>>> g.get_point_count()
12
>>> g.get_cell_count()
6
>>> g.get_x()
array([ 1.,  2.,  4.,  8.,  1.,  2.,  4.,  8.,  1.,  2.,  4.,  8.])
>>> g.get_y()
array([ 1.,  1.,  1.,  1.,  2.,  2.,  2.,  2.,  3.,  3.,  3.,  3.])
>>> g.get_shape()
array([3, 4])

Create a grid of length 2 in the i direction, and 3 in the j direction.

>>> (x, y) = np.meshgrid ([1., 2., 4., 8.], [1., 2., 3.])
>>> g = Structured (y.flatten (), x.flatten (), (3, 4), indexing='ij')
>>> g.get_x()
array([ 1.,  2.,  4.,  8.,  1.,  2.,  4.,  8.,  1.,  2.,  4.,  8.])
>>> g.get_y()
array([ 1.,  1.,  1.,  1.,  2.,  2.,  2.,  2.,  3.,  3.,  3.,  3.])
>>> g.get_shape()
array([3, 4])
>>> g.get_offset()
array([ 4,  8, 12, 16, 20, 24])
>>> g.get_connectivity()
array([ 0,  1,  5,  4,  1,  2,  6,  5,  2,  3,  7,  6,  4,  5,  9,  8,  5,
        6, 10,  9,  6,  7, 11, 10])

Structured grid of points

The same grid as the previous example but without any cells - just points.

>>> (x, y) = np.meshgrid ([1., 2., 4., 8.], [1., 2., 3.])
>>> g = StructuredPoints (y.flatten (), x.flatten (), (3, 4), indexing='ij', set_connectivity=True)
>>> g.get_x()
array([ 1.,  2.,  4.,  8.,  1.,  2.,  4.,  8.,  1.,  2.,  4.,  8.])
>>> g.get_y()
array([ 1.,  1.,  1.,  1.,  2.,  2.,  2.,  2.,  3.,  3.,  3.,  3.])
>>> g.get_shape()
array([3, 4])

The number of points are the same, but the number of cells is now 0.

>>> g.get_point_count()
12
>>> g.get_cell_count()
0

The offset runs from 1 up to (and including) the number of points.

>>> all (g.get_offset ()==np.arange (1, g.get_point_count ()+1))
True

The connectivity runs from 0 to one less than the number of points.

>>> all (g.get_connectivity ()==np.arange (g.get_point_count ()))
True

1D Grid of line segments

>>> g = Structured([-1, 2, 3, 6], (4, ))
>>> g.get_x()
array([-1.,  2.,  3.,  6.])
>>> g.get_y()
Traceback (most recent call last):
        ...
IndexError: Dimension out of bounds
>>> g.get_shape()
array([4])
>>> g.get_offset()
array([2, 4, 6])
>>> g.get_connectivity()
array([0, 1, 1, 2, 2, 3])

3D Grid of cubes

>>> x = [0, 1, 0, 1, 0, 1, 0, 1]
>>> y = [0, 0, 1, 1, 0, 0, 1, 1]
>>> z = [0, 0, 0, 0, 1, 1, 1, 1]
>>> g = Structured(z, y, x, (2, 2, 2))
>>> g.get_x()
array([ 0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.])
>>> g.get_y()
array([ 0.,  0.,  1.,  1.,  0.,  0.,  1.,  1.])
>>> g.get_z()
array([ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.])
>>> g.get_connectivity()
array([0, 1, 3, 2, 4, 5, 7, 6])
>>> g.get_offset()
array([8])
>>> g = Structured(x, y, z, (2, 2, 2), ordering='ccw')
>>> g.get_connectivity()
array([1, 0, 2, 3, 5, 4, 6, 7])
class pymt.grids.structured.Structured(*args, **kwds)[source]

Bases: pymt.grids.structured.StructuredPoints, pymt.grids.unstructured.Unstructured

Create a structured rectilinear grid.

Parameters:
  • x (ndarray) – 1-D array of x-coordinates of nodes.
  • y (ndarray) – 1-D array of y-coordinates of nodes.
  • shape (tuple of int) – Shape of the grid.
  • indexing ({'xy', 'ij'}, optional) – Cartesian(‘xy’, default) or matrix(‘ij’) indexing of output.
Returns:

An instance of a Structured grid.

Return type:

Structured

class pymt.grids.structured.StructuredPoints(*args, **kwds)[source]

Bases: pymt.grids.unstructured.UnstructuredPoints

__init__(*args, **kwds)[source]

StructuredPoints(x0 [, x1 [, x2]], shape)

get_coordinate(i)[source]
get_coordinate_name(i)[source]
get_coordinate_units(i)[source]
get_point_coordinates(*args, **kwds)[source]
get_shape(remove_singleton=False)[source]

The shape of the structured grid with the given indexing.

Use remove_singleton=False to include singleton dimensions.

pymt.grids.unstructured module
class pymt.grids.unstructured.Unstructured(*args, **kwds)[source]

Bases: pymt.grids.unstructured.UnstructuredPoints

Define a grid that consists of two trianges that share two points:

   (2) - (3)
  /   \  /
(0) - (1)

Create the grid,

>>> g = Unstructured([0, 0, 1, 1], [0, 2, 1, 3],
...                  connectivity=[0, 2, 1, 2, 3, 1], offset=[3, 6])
>>> g.get_point_count()
4
>>> g.get_cell_count()
2
>>> g.get_dim_count()
2
>>> g.get_x()
array([ 0.,  2.,  1.,  3.])
>>> g.get_y()
array([ 0.,  0.,  1.,  1.])
>>> g.get_connectivity()
array([0, 2, 1, 2, 3, 1])
>>> g.get_offset()
array([3, 6])

Define a grid that consists of points in a line:

(0) ----- (1) -- (2) - (3)

Create the grid,

>>> g = Unstructured ([0., 6., 9., 11.], connectivity=[0, 1, 2, 3], offset=[1, 2, 3, 4])
>>> g.get_point_count ()
4
>>> g.get_cell_count ()
4

Eight point that form a unit cube.

>>> x = [0, 1, 0, 1, 0, 1, 0, 1]
>>> y = [0, 0, 1, 1, 0, 0, 1, 1]
>>> z = [0, 0, 0, 0, 1, 1, 1, 1]
>>> g = Unstructured(z, y, x, connectivity=[0, 1, 2, 3, 4, 5, 6, 7], offset=[8])
>>> g.get_point_count()
8
>>> g.get_cell_count()
1
>>> g.get_x()
array([ 0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.])
>>> g.get_y()
array([ 0.,  0.,  1.,  1.,  0.,  0.,  1.,  1.])
>>> g.get_z()
array([ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.])
class pymt.grids.unstructured.UnstructuredPoints(*args, **kwds)[source]

Bases: pymt.grids.igrid.IGrid

__init__(*args, **kwds)[source]

UnstructuredPoints(x0 [, x1 [, x2]])

get_attrs()[source]
get_axis_coordinates(axis=None, indexing='ij')[source]
get_cell_count()[source]
get_connectivity()[source]

Return the connectivity array for the grid.

get_connectivity_as_matrix(fill_val=9223372036854775807)[source]
get_coordinate(i)[source]
get_coordinate_name(i)[source]
get_coordinate_units(i)[source]
get_dim_count()[source]
get_max_vertices()[source]
get_offset()[source]

Return an array of offsets in to the connectivity array for each element of the grid.

get_point_coordinates(*args, **kwds)[source]
get_point_count()[source]
get_vertex_count()[source]
get_x()[source]

Return the x-coordinates of the grid nodes.

get_x_units()[source]
get_xyz()[source]
get_y()[source]

Return the y-coordinates of the grid nodes.

get_y_units()[source]
get_z()[source]
get_z_units()[source]
nodes_per_cell()[source]
reverse_element_ordering()[source]
set_x_units(units)[source]
set_y_units(units)[source]
set_z_units(units)[source]
pymt.grids.utils module
pymt.grids.utils.args_as_numpy_arrays(*args)[source]
pymt.grids.utils.assert_arrays_are_equal_size(*args)[source]
pymt.grids.utils.connectivity_matrix_as_array(face_nodes, bad_val)[source]
pymt.grids.utils.coordinates_to_numpy_matrix(*args)[source]
pymt.grids.utils.get_default_coordinate_names(n_dims)[source]
pymt.grids.utils.get_default_coordinate_units(n_dims)[source]
pymt.grids.utils.non_singleton_axes(grid)[source]
pymt.grids.utils.non_singleton_coordinate_names(grid)[source]
pymt.grids.utils.non_singleton_dimension_names(grid)[source]
pymt.grids.utils.non_singleton_dimension_shape(grid)[source]
pymt.grids.utils.non_singleton_shape(grid)[source]
Module contents
class pymt.grids.UniformRectilinear(shape, spacing, origin, **kwds)[source]

Bases: pymt.grids.raster.UniformRectilinearPoints, pymt.grids.rectilinear.Rectilinear

Create a rectilinear grid with uniform spacing in the x and y directions.

Parameters:
  • shape (tuple of int) – Grid shape measured in number of nodes.
  • spacing (tuple of int) – Spacing between nodes in each direction of a rectilinear grid.
  • origin (tuple of int) – Coordinates of the lower-left corner of the grid.
  • indexing ({'xy', 'ij'}, optional) – Cartesian (‘xy’, default) or matrix (‘ij’) indexing of output. See Notes for more details.
Returns:

An instance of a UniformRectilinear grid.

Return type:

UniformRectilinear

class pymt.grids.UniformRectilinearPoints(shape, spacing, origin, **kwds)[source]

Bases: pymt.grids.rectilinear.RectilinearPoints

get_origin()[source]

Coordinates of the grid’s lower-left corner

get_spacing()[source]

Spacing between nodes in each direction

class pymt.grids.Rectilinear(*args, **kwds)[source]

Bases: pymt.grids.rectilinear.RectilinearPoints, pymt.grids.structured.Structured

Create a rectilinear grid.

Parameters:
  • x (ndarray) – 1-D array of x-coordinates of nodes.
  • y (ndarray) – 1-D array of y-coordinates of nodes.
  • shape (tuple of int) – Grid shape measured in number of nodes
  • indexing ({'xy', 'ij'}, optional) – Cartesian (‘xy’, default) or matrix (‘ij’) indexing of output.
Returns:

An instance of a Rectilinear grid.

Return type:

Rectilinear

class pymt.grids.RectilinearPoints(*args, **kwds)[source]

Bases: pymt.grids.structured.StructuredPoints

get_axis_coordinates(axis=None, indexing='ij')[source]
get_x_coordinates()[source]

Examples

>>> g = Rectilinear([0, 1], [2, 3], [4, 5], set_connectivity=True, indexing='ij')
>>> g.get_x_coordinates()
array([ 4.,  5.])
get_xyz_coordinates()[source]
get_y_coordinates()[source]

Examples

>>> g = Rectilinear([0, 1], [2, 3], [4, 5], set_connectivity=True, indexing='ij')
>>> g.get_y_coordinates()
array([ 2.,  3.])
get_z_coordinates()[source]

Examples

>>> g = Rectilinear([0, 1], [2, 3], [4, 5], set_connectivity=True, indexing='ij')
>>> g.get_z_coordinates()
array([ 0.,  1.])
class pymt.grids.Structured(*args, **kwds)[source]

Bases: pymt.grids.structured.StructuredPoints, pymt.grids.unstructured.Unstructured

Create a structured rectilinear grid.

Parameters:
  • x (ndarray) – 1-D array of x-coordinates of nodes.
  • y (ndarray) – 1-D array of y-coordinates of nodes.
  • shape (tuple of int) – Shape of the grid.
  • indexing ({'xy', 'ij'}, optional) – Cartesian(‘xy’, default) or matrix(‘ij’) indexing of output.
Returns:

An instance of a Structured grid.

Return type:

Structured

class pymt.grids.StructuredPoints(*args, **kwds)[source]

Bases: pymt.grids.unstructured.UnstructuredPoints

__init__(*args, **kwds)[source]

StructuredPoints(x0 [, x1 [, x2]], shape)

get_coordinate(i)[source]
get_coordinate_name(i)[source]
get_coordinate_units(i)[source]
get_point_coordinates(*args, **kwds)[source]
get_shape(remove_singleton=False)[source]

The shape of the structured grid with the given indexing.

Use remove_singleton=False to include singleton dimensions.

class pymt.grids.Unstructured(*args, **kwds)[source]

Bases: pymt.grids.unstructured.UnstructuredPoints

Define a grid that consists of two trianges that share two points:

   (2) - (3)
  /   \  /
(0) - (1)

Create the grid,

>>> g = Unstructured([0, 0, 1, 1], [0, 2, 1, 3],
...                  connectivity=[0, 2, 1, 2, 3, 1], offset=[3, 6])
>>> g.get_point_count()
4
>>> g.get_cell_count()
2
>>> g.get_dim_count()
2
>>> g.get_x()
array([ 0.,  2.,  1.,  3.])
>>> g.get_y()
array([ 0.,  0.,  1.,  1.])
>>> g.get_connectivity()
array([0, 2, 1, 2, 3, 1])
>>> g.get_offset()
array([3, 6])

Define a grid that consists of points in a line:

(0) ----- (1) -- (2) - (3)

Create the grid,

>>> g = Unstructured ([0., 6., 9., 11.], connectivity=[0, 1, 2, 3], offset=[1, 2, 3, 4])
>>> g.get_point_count ()
4
>>> g.get_cell_count ()
4

Eight point that form a unit cube.

>>> x = [0, 1, 0, 1, 0, 1, 0, 1]
>>> y = [0, 0, 1, 1, 0, 0, 1, 1]
>>> z = [0, 0, 0, 0, 1, 1, 1, 1]
>>> g = Unstructured(z, y, x, connectivity=[0, 1, 2, 3, 4, 5, 6, 7], offset=[8])
>>> g.get_point_count()
8
>>> g.get_cell_count()
1
>>> g.get_x()
array([ 0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.])
>>> g.get_y()
array([ 0.,  0.,  1.,  1.,  0.,  0.,  1.,  1.])
>>> g.get_z()
array([ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.])
class pymt.grids.UnstructuredPoints(*args, **kwds)[source]

Bases: pymt.grids.igrid.IGrid

__init__(*args, **kwds)[source]

UnstructuredPoints(x0 [, x1 [, x2]])

get_attrs()[source]
get_axis_coordinates(axis=None, indexing='ij')[source]
get_cell_count()[source]
get_connectivity()[source]

Return the connectivity array for the grid.

get_connectivity_as_matrix(fill_val=9223372036854775807)[source]
get_coordinate(i)[source]
get_coordinate_name(i)[source]
get_coordinate_units(i)[source]
get_dim_count()[source]
get_max_vertices()[source]
get_offset()[source]

Return an array of offsets in to the connectivity array for each element of the grid.

get_point_coordinates(*args, **kwds)[source]
get_point_count()[source]
get_vertex_count()[source]
get_x()[source]

Return the x-coordinates of the grid nodes.

get_x_units()[source]
get_xyz()[source]
get_y()[source]

Return the y-coordinates of the grid nodes.

get_y_units()[source]
get_z()[source]
get_z_units()[source]
nodes_per_cell()[source]
reverse_element_ordering()[source]
set_x_units(units)[source]
set_y_units(units)[source]
set_z_units(units)[source]
class pymt.grids.RasterField(shape, spacing, origin, **kwds)[source]

Bases: pymt.grids.raster.UniformRectilinear, pymt.grids.field.StructuredField

Create a field that looks like this,

(0) --- (1) --- (2)
 |       |       |
 |   0   |   1   |
 |       |       |
(3) --- (4) --- (5)

Create the field,

>>> g = RasterField ((2,3), (1,2), (0, 0), indexing='ij')
>>> g.get_cell_count ()
2
>>> g.get_point_count ()
6

Add some data at the points of our grid.

>>> data = np.arange (6)
>>> g.add_field ('var0', data, centering='point')
>>> g.get_field ('var0')
array([0, 1, 2, 3, 4, 5])

The data can be given either as a 1D array or with the same shape as the point grid. In either case, though, it will be flattened.

>>> data = np.arange (6)
>>> data.shape = (2, 3)
>>> g.add_field ('var0', data, centering='point')
>>> g.get_field ('var0')
array([0, 1, 2, 3, 4, 5])

If the size or shape doesn’t match, it’s an error.

>>> data = np.arange (2)
>>> g.add_field ('bad var', data, centering='point') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
DimensionError: 2 != 6
>>> data = np.ones ((3, 2))
>>> g.add_field ('bad var', data, centering='point') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
DimensionError: (3, 2) != (2, 3)

Add data to the cells of the grid. Again, the data can be given as a 1D array or with the same shape as the cell grid and if the size or shape doesn’t match raise an exception.

>>> data = np.arange (2)
>>> g.add_field('var1', data, centering='zonal')
>>> g.get_field('var1')
array([0, 1])
>>> data = np.ones((2, 1))
>>> g.add_field('bad var', data, centering='zonal') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
DimensionError: (2, 1) != (1, 2)
>>> data = np.arange(3)
>>> g.add_field('bad var', data, centering='zonal') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
DimensionError: 3 != 2
>>> data = np.array(3)
>>> g.add_field('bad var', data, centering='zonal')  # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
DimensionError: 1 != 2

A 1D-Field,

>>> g = RasterField ((6, ), (1.5, ), (0.5, ), indexing='ij')
>>> g.get_point_count ()
6
>>> g.get_cell_count ()
5
>>> point_data = np.arange (6.)
>>> g.add_field ('Point Data', point_data, centering='point')
>>> cell_data = np.arange (5.)*10.
>>> g.add_field ('Cell Data', cell_data, centering='zonal')
>>> g.get_field ('Cell Data')
array([  0.,  10.,  20.,  30.,  40.])
>>> g.get_field ('Point Data')
array([ 0.,  1.,  2.,  3.,  4.,  5.])

A 3D-Field,

>>> g = RasterField ((4, 3, 2), (1.5, 1., 3), (0.5, 0, -.5 ), indexing='ij')
>>> g.get_point_count ()
24
>>> g.get_cell_count ()
6
>>> g.add_field ('Point Data', g.get_x (), centering='point')
>>> cell_data = np.arange (6.)*10.
>>> g.add_field ('Cell Data', cell_data, centering='zonal')
>>> g.get_field ('Cell Data')
array([  0.,  10.,  20.,  30.,  40.,  50.])
>>> g.get_field('Point Data')
array([-0.5,  2.5, -0.5,  2.5, -0.5,  2.5, -0.5,  2.5, -0.5,  2.5, -0.5,
        2.5, -0.5,  2.5, -0.5,  2.5, -0.5,  2.5, -0.5,  2.5, -0.5,  2.5,
       -0.5,  2.5])
>>> g.get_shape()
array([4, 3, 2])
>>> g.get_x().size == g.get_field('Point Data').size
True
>>> x = g.get_x()
>>> x.shape
(24,)
>>> x.shape = g.get_shape()
>>> x.shape
(4, 3, 2)
class pymt.grids.RectilinearField(*args, **kwds)[source]

Bases: pymt.grids.rectilinear.Rectilinear, pymt.grids.field.StructuredField

class pymt.grids.StructuredField(*args, **kwds)[source]

Bases: pymt.grids.structured.Structured, pymt.grids.field.GridField

add_field(field_name, val, centering='zonal', units='-', exist_action='clobber', time=None)[source]
class pymt.grids.UnstructuredField(*args, **kwargs)[source]

Bases: pymt.grids.field.GridField

pymt.grids.is_uniform_rectilinear(grid)[source]
pymt.grids.is_rectilinear(grid, strict=True)[source]
pymt.grids.is_structured(grid, strict=True)[source]
pymt.grids.is_unstructured(grid, strict=True)[source]
exception pymt.grids.DimensionError(dim0, dim1)[source]

Bases: pymt.grids.igrid.Error

Error to indicate a dimension mismatch when adding a value field to a grid.

pymt.mappers package
Submodules
pymt.mappers.celltopoint module
class pymt.mappers.celltopoint.CellToPoint[source]

Bases: pymt.mappers.imapper.IGridMapper

initialize(dest_grid, src_grid, **kwds)[source]

Initialize the mapper to map from a source grid to a destination grid.

name
run(src_values, **kwds)[source]

Map values on the source grid to the destination grid.

static test(dst_grid, src_grid)[source]
pymt.mappers.celltopoint.map_points_to_cells(coords, src_grid, src_point_ids, bad_val=-1)[source]
pymt.mappers.esmp module
class pymt.mappers.esmp.EsmpCellToCell[source]

Bases: pymt.mappers.esmp.EsmpMapper

init_fields()[source]
static test(dst_grid, src_grid)[source]
class pymt.mappers.esmp.EsmpMapper[source]

Bases: pymt.mappers.imapper.IGridMapper

finalize()[source]
get_dest_data()[source]
get_dest_field()[source]
get_source_data()[source]
get_source_field()[source]
init_fields()[source]
initialize(dest_grid, src_grid, **kwds)[source]

Initialize the mapper to map from a source grid to a destination grid.

name
run(src_values, **kwds)[source]

Map values on the source grid to the destination grid.

static test(dst_grid, src_grid)[source]
class pymt.mappers.esmp.EsmpPointToPoint[source]

Bases: pymt.mappers.esmp.EsmpMapper

init_fields()[source]
static test(dst_grid, src_grid)[source]
pymt.mappers.imapper module
class pymt.mappers.imapper.IGridMapper[source]

Bases: object

Interface for a grid mapper.

initialize(dest_grid, src_grid, **kwds)[source]

Initialize the mapper to map from a source grid to a destination grid.

run(src_values, **kwds)[source]

Map values on the source grid to the destination grid.

exception pymt.mappers.imapper.IncompatibleGridError(dst, src)[source]

Bases: pymt.mappers.imapper.MapperError

Error to indicate that the source grid cannot be mapped to the destination.

exception pymt.mappers.imapper.MapperError[source]

Bases: Exception

Base class for error in this package.

exception pymt.mappers.imapper.NoMapperError(dst, src)[source]

Bases: pymt.mappers.imapper.MapperError

pymt.mappers.mapper module

Examples

Point-to-point Mapping
>>> import numpy as np
>>> from pymt.grids.map import RectilinearMap as Rectilinear
>>> src = Rectilinear([0, 1, 2], [0, 2])
>>> dst = Rectilinear([.5, 1.5, 2.5], [.25, 1.25])
>>> src.get_x()
array([ 0.,  2.,  0.,  2.,  0.,  2.])
>>> src.get_y()
array([ 0.,  0.,  1.,  1.,  2.,  2.])
>>> dst.get_x()
array([ 0.25,  1.25,  0.25,  1.25,  0.25,  1.25])
>>> dst.get_y()
array([ 0.5,  0.5,  1.5,  1.5,  2.5,  2.5])
>>> src_vals = np.arange(src.get_point_count(), dtype=np.float64)

Map the source values on the source points to the destination grid using nearest neighbor.

>>> from pymt.mappers import NearestVal
>>> mapper = NearestVal()
>>> mapper.initialize(dst, src)
>>> mapper.run(src_vals)
array([ 0.,  1.,  2.,  3.,  4.,  5.])
>>> mappers = find_mapper(dst, src)
>>> len(mappers)
3
>>> mappers[0].name
'PointToPoint'
>>> src_vals[2] = -999
>>> dst_vals = np.full(dst.get_point_count(), -1.)
>>> mapper.run(src_vals, dst_vals=dst_vals)
array([ 0.,  1., -1.,  3.,  4.,  5.])
Cell-to-point Mapping

The source grid looks like,

(0) ------ (1)
 |          |
 |          |
(2) ------ (3)
 |          |
 |          |
(4) ------ (5)
 |          |
 |          |
(7) ------ (7)
>>> from pymt.mappers import CellToPoint
>>> from pymt.grids.map import UniformRectilinearMap as UniformRectilinear
>>> from pymt.grids.map import UnstructuredPointsMap as UnstructuredPoints
>>> (dst_x, dst_y) = (np.array([.45, 1.25, 3.5]), np.array([.75, 2.25, 3.25]))
>>> src = UniformRectilinear((2,4), (2, 1), (0, 0))
>>> dst = UnstructuredPoints(dst_x, dst_y)
>>> src_vals = np.arange(src.get_cell_count(), dtype=np.float64)
>>> mapper = CellToPoint()
>>> mapper.initialize(dst, src)
>>> mapper.run(src_vals, bad_val=-999)
array([   0.,    2., -999.])
>>> src_vals = np.arange(src.get_cell_count(), dtype=np.float64)
>>> src_vals[0] = -9999
>>> dst_vals = np.zeros(dst.get_point_count()) + 100
>>> _ = mapper.run(src_vals, dst_vals=dst_vals)
>>> dst_vals
array([ 100.,    2., -999.])
Point-to-cell Mapping
>>> from pymt.mappers.pointtocell import PointToCell
>>> (src_x, src_y) = (np.array ([.45, 1.25, 3.5, .0, 1.]),
...                   np.array ([.75, 2.25, 3.25, .9, 1.1]))
>>> src = UnstructuredPoints(src_x, src_y)
>>> dst = UniformRectilinear((2,4), (2, 1), (0, 0))
>>> src_vals = np.arange(src.get_point_count(), dtype=np.float64)
>>> mapper = PointToCell()
>>> mapper.initialize(dst, src)
>>> mapper.run(src_vals, bad_val=-999)
array([ 1.5,  4. ,  1. ])
>>> mapper.run(src_vals, bad_val=-999, method=np.sum)
array([ 3.,  4.,  1.])
>>> src_vals[0] = -9999
>>> dst_vals = np.zeros(dst.get_cell_count ()) - 1
>>> _ = mapper.run(src_vals, dst_vals=dst_vals)
>>> dst_vals
array([-1.,  4.,  1.])
Point on cell edges
>>> (src_x, src_y) = (np.array ([0, .5, 1., 2, 3.5]),
...                   np.array ([1., 1., .0, 3, 3.]))
>>> src = UnstructuredPoints(src_x, src_y)
>>> dst = UniformRectilinear((2,4), (2, 1), (0, 0))
>>> mapper = PointToCell()
>>> mapper.initialize(dst, src)
>>> src_vals = np.arange(src.get_point_count(), dtype=np.float64)
>>> dst_vals = np.zeros(dst.get_cell_count()) - 1
>>> _ = mapper.run(src_vals, dst_vals=dst_vals)
>>> dst_vals
array([ 1. ,  0.5,  3. ])
A big mapper
>>> (m, n) = (20, 40)
>>> (src_x, src_y) = np.meshgrid(range(m), range(n))
>>> src = UnstructuredPoints(src_y, src_x)
>>> dst = UniformRectilinear((n + 1, m + 1), (1, 1), (-.5, -.5))
>>> mapper = PointToCell()
>>> mapper.initialize(dst, src)
>>> src_vals = np.arange(src.get_point_count(), dtype=np.float64)
>>> dst_vals = np.zeros(dst.get_cell_count(), dtype=np.float64) - 1
>>> _ = mapper.run(src_vals, dst_vals=dst_vals)
>>> from numpy.testing import assert_array_equal
>>> assert_array_equal(dst_vals, src_vals)
pymt.mappers.mapper.find_mapper(dst_grid, src_grid)[source]

Find appropriate mappers to map bewteen two grid-like objects

pymt.mappers.pointtocell module
class pymt.mappers.pointtocell.PointToCell[source]

Bases: pymt.mappers.imapper.IGridMapper

initialize(dest_grid, src_grid, **kwds)[source]

Initialize the mapper to map from a source grid to a destination grid.

name
run(src_values, **kwds)[source]

Map values on the source grid to the destination grid.

static test(dst_grid, src_grid)[source]
pymt.mappers.pointtocell.map_cells_to_points(coords, dst_grid, dst_point_ids, bad_val=-1)[source]
pymt.mappers.pointtopoint module
class pymt.mappers.pointtopoint.NearestVal[source]

Bases: pymt.mappers.imapper.IGridMapper

Examples

>>> import numpy as np
>>> from pymt.grids.map import RectilinearMap
>>> from pymt.mappers.pointtopoint import NearestVal
>>> src = RectilinearMap([0, 1, 2], [0, 2])
>>> dst = RectilinearMap([.25, 1.25, 2.25], [.25, 1.25])
>>> mapper = NearestVal()
>>> mapper.initialize(dst, src)
>>> mapper.run(np.arange(6.))
array([ 0.,  1.,  2.,  3.,  4.,  5.])
initialize(dest_grid, src_grid, **kwds)[source]

Map points on one grid to the nearest points on another.

Parameters:
  • dest_grid (grid_like) – Grid onto which points are mapped
  • src_grid (grid_like) – Grid from which points are taken.
  • var_names (iterable of tuples (optional)) – Iterable of (dest, src) variable names.
name

Name of the grid mapper.

run(src_values, **kwds)[source]

Map source values onto destination values.

Parameters:
  • src_values (ndarray) – Source values at points.
  • dst_vals (ndarray (optional)) – Destination array to put mapped values.
Returns:

dest – The (possibly newly-created) destination array.

Return type:

ndarray

static test(dst_grid, src_grid)[source]

Test if grids are compatible with this mapper.

Parameters:
  • dst_grid (grid_like) – Grid onto which points are mapped
  • src_grid (grid_like) – Grid from which points are taken.
pymt.mappers.pointtopoint.copy_good_values(src, dst, bad_val=-999)[source]

Copy only the good values from one array to another.

Parameters:
  • src (array_like) – Array of source values.
  • dst (array_like) – Array into which to copy the good values.
  • bad_val (float (optional)) – Value below which indicates a bad value.
Returns:

dst – The destination array.

Return type:

array_like

Examples

>>> import numpy as np
>>> from pymt.mappers.pointtopoint import copy_good_values
>>> x = np.arange(6)
>>> y = np.zeros((2, 3))
>>> rv = copy_good_values(x, y)
>>> rv is y
True
>>> y
array([[ 0.,  1.,  2.],
       [ 3.,  4.,  5.]])
>>> copy_good_values(x, np.zeros(6), bad_val=3.)
array([ 0.,  0.,  0.,  0.,  4.,  5.])
Module contents
pymt.mappers.find_mapper(dst_grid, src_grid)[source]

Find appropriate mappers to map bewteen two grid-like objects

exception pymt.mappers.IncompatibleGridError(dst, src)[source]

Bases: pymt.mappers.imapper.MapperError

Error to indicate that the source grid cannot be mapped to the destination.

class pymt.mappers.CellToPoint[source]

Bases: pymt.mappers.imapper.IGridMapper

initialize(dest_grid, src_grid, **kwds)[source]

Initialize the mapper to map from a source grid to a destination grid.

name
run(src_values, **kwds)[source]

Map values on the source grid to the destination grid.

static test(dst_grid, src_grid)[source]
class pymt.mappers.NearestVal[source]

Bases: pymt.mappers.imapper.IGridMapper

Examples

>>> import numpy as np
>>> from pymt.grids.map import RectilinearMap
>>> from pymt.mappers.pointtopoint import NearestVal
>>> src = RectilinearMap([0, 1, 2], [0, 2])
>>> dst = RectilinearMap([.25, 1.25, 2.25], [.25, 1.25])
>>> mapper = NearestVal()
>>> mapper.initialize(dst, src)
>>> mapper.run(np.arange(6.))
array([ 0.,  1.,  2.,  3.,  4.,  5.])
initialize(dest_grid, src_grid, **kwds)[source]

Map points on one grid to the nearest points on another.

Parameters:
  • dest_grid (grid_like) – Grid onto which points are mapped
  • src_grid (grid_like) – Grid from which points are taken.
  • var_names (iterable of tuples (optional)) – Iterable of (dest, src) variable names.
name

Name of the grid mapper.

run(src_values, **kwds)[source]

Map source values onto destination values.

Parameters:
  • src_values (ndarray) – Source values at points.
  • dst_vals (ndarray (optional)) – Destination array to put mapped values.
Returns:

dest – The (possibly newly-created) destination array.

Return type:

ndarray

static test(dst_grid, src_grid)[source]

Test if grids are compatible with this mapper.

Parameters:
  • dst_grid (grid_like) – Grid onto which points are mapped
  • src_grid (grid_like) – Grid from which points are taken.
class pymt.mappers.PointToCell[source]

Bases: pymt.mappers.imapper.IGridMapper

initialize(dest_grid, src_grid, **kwds)[source]

Initialize the mapper to map from a source grid to a destination grid.

name
run(src_values, **kwds)[source]

Map values on the source grid to the destination grid.

static test(dst_grid, src_grid)[source]
pymt.portprinter package
Submodules
pymt.portprinter.port_printer module
class pymt.portprinter.port_printer.NcPortPrinter(port, var_name, filename=None)[source]

Bases: pymt.portprinter.port_printer.PortPrinter

class pymt.portprinter.port_printer.PortPrinter(port, var_name, filename=None)[source]

Bases: object

close()[source]
format
classmethod from_dict(d)[source]
classmethod from_path(path, prefix='print')[source]
classmethod from_string(source, prefix='print')[source]
open(clobber=False)[source]
resync_field_to_port()[source]
var_name
write()[source]
pymt.portprinter.utils module
exception pymt.portprinter.utils.BadFileFormatError(fmt)[source]

Bases: pymt.portprinter.utils.Error

exception pymt.portprinter.utils.DimensionError(msg)[source]

Bases: pymt.portprinter.utils.Error

exception pymt.portprinter.utils.Error[source]

Bases: Exception

pymt.portprinter.utils.construct_file_name(var_name, template='${var}', fmt=None, prefix='')[source]
pymt.portprinter.utils.construct_port_as_field(port, var_name)[source]

Create a field object from a port.

Parameters:
  • port (port_like) – A port.
  • var_name (str) – Name of the variable field.
Returns:

A newly created field that contains the data for var_name.

Return type:

field_like

pymt.portprinter.utils.data_is_centered_on_cells(field, data)[source]
pymt.portprinter.utils.data_is_centered_on_points(field, data)[source]
pymt.portprinter.utils.find_unknown_dimension(shape)[source]

Find unlimited dimensions.

If a dimension is negative, it’s thought to be unknown or unlimited Find that dimension. Raise an error if there are multiple unknown dimensions.

Parameters:shape (ndarray of int) – Array shape.
Returns:Dimension that is unknown or None if all dimensions are known.
Return type:int
Raises:DimensionError – There are multiple unknown dimensions.
pymt.portprinter.utils.fix_unknown_shape(shape, size)[source]

Determine shape with an unknown dimension.

Parameters:
  • shape (ndarray of int) – Array shape (with a possible unknown dimension).
  • size (int) – Sive of the array.
Returns:

Shape of the array with any unknown dimension fixed.

Return type:

tuple of int

Examples

>>> from pymt.portprinter.utils import fix_unknown_shape
>>> fix_unknown_shape((4, 3), 12)
(4, 3)
>>> fix_unknown_shape((4, -1), 12)
(4, 3)
pymt.portprinter.utils.format_to_file_extension(fmt)[source]
pymt.portprinter.utils.get_data_centering(field, data_array)[source]
pymt.portprinter.utils.is_rectilinear_port(port, grid_id)[source]
pymt.portprinter.utils.is_structured_port(port, grid_id)[source]
pymt.portprinter.utils.mesh_size_has_changed(field, data)[source]
pymt.portprinter.utils.next_unique_file_name(file_name)[source]
pymt.portprinter.utils.normalize_format_name(fmt)[source]
pymt.portprinter.utils.port_is_one_point(port, grid_id)[source]
pymt.portprinter.utils.positive_dimensions(shape)[source]

Check if all dimensions are positive.

Parameters:shape (ndarray of int) – Array shape.
Returns:True if dimensions are positive non-zero. Otherwise, False.
Return type:boolean
pymt.portprinter.utils.reconstruct_port_as_field(port, field)[source]

Recreate a field object from a port.

Add data from port to field. If the mesh of the port is no longer the same as that of field, create a new field object and add the data to it. Where possible, the new data is added to the existing field. Only the data that does not fit on the existing field is added to the new one.

Parameters:
  • port (port_like) – A port.
  • field (field_like) – An existing field with new data.
Returns:

A (possibley) newly created field that contains the data for var_name.

Return type:

field_like

Module contents
pymt.printers package
Subpackages
pymt.printers.nc package
Submodules
pymt.printers.nc.constants module
pymt.printers.nc.constants.assert_valid_netcdf_format(fmt)[source]
pymt.printers.nc.constants.open_netcdf(path, mode='r', fmt='NETCDF3_CLASSIC', append=False)[source]
pymt.printers.nc.database module
class pymt.printers.nc.database.Database[source]

Bases: pymt.printers.nc.database.IDatabase

close()[source]
open(path, var_name, **kwds)[source]
write(field, **kwds)[source]
class pymt.printers.nc.database.IDatabase[source]

Bases: object

close()[source]
open(path, var_name, **kwds)[source]
write(field, **kwds)[source]
pymt.printers.nc.database.field_changed_size(field, n_points, n_cells)[source]
pymt.printers.nc.read module
pymt.printers.nc.read.field_fromfile(path, fmt='NETCDF4')[source]
pymt.printers.nc.read.query_netcdf_mesh_type(path, fmt='NETCDF4')[source]
pymt.printers.nc.ugrid module
class pymt.printers.nc.ugrid.NetcdfField(path, field, fmt='NETCDF4', append=False, time=None, keep_open=False)[source]

Bases: object

close()[source]
create_dimension(name, dim_len)[source]
create_variable(name, *args, **kwds)[source]
data_variable(name)[source]
face_connectivity
face_count
face_data_dimensions
face_node_connectivity
field
field_axes
has_dimension(name)[source]
has_variable(name)[source]
node_coordinates
node_count
node_data_dimensions
root
set_variable(name, *args, **kwds)[source]
time_count
topology_dimension
type
vertex_count
class pymt.printers.nc.ugrid.NetcdfRectilinearField(path, field, fmt='NETCDF4', append=False, time=None, keep_open=False)[source]

Bases: pymt.printers.nc.ugrid.NetcdfField

axis_coordinates
node_coordinates
node_data_dimensions
topology_dimension
type
class pymt.printers.nc.ugrid.NetcdfStructuredField(path, field, fmt='NETCDF4', append=False, time=None, keep_open=False)[source]

Bases: pymt.printers.nc.ugrid.NetcdfRectilinearField

node_coordinates
node_data_dimensions
type
class pymt.printers.nc.ugrid.NetcdfUnstructuredField(path, field, fmt='NETCDF4', append=False, time=None, keep_open=False)[source]

Bases: pymt.printers.nc.ugrid.NetcdfStructuredField

face_data_dimensions
node_coordinates
node_data_dimensions
topology_dimension
type
pymt.printers.nc.ugrid.close(path)[source]
pymt.printers.nc.ugrid.close_all()[source]
pymt.printers.nc.ugrid_read module
class pymt.printers.nc.ugrid_read.NetcdfFieldReader(path, fmt='NETCDF4')[source]

Bases: object

contains_time_dimension()[source]
fields
is_variable_data(name)[source]
time
times
variable_data(name)[source]
variable_data_names()[source]
class pymt.printers.nc.ugrid_read.NetcdfRectilinearFieldReader(path, fmt='NETCDF4')[source]

Bases: pymt.printers.nc.ugrid_read.NetcdfFieldReader

class pymt.printers.nc.ugrid_read.NetcdfStructuredFieldReader(path, fmt='NETCDF4')[source]

Bases: pymt.printers.nc.ugrid_read.NetcdfFieldReader

class pymt.printers.nc.ugrid_read.NetcdfUnstructuredFieldReader(path, fmt='NETCDF4')[source]

Bases: pymt.printers.nc.ugrid_read.NetcdfFieldReader

face_nodes_data()[source]
face_nodes_fill_value()[source]
face_nodes_start_index()[source]
pymt.printers.nc.write module
pymt.printers.nc.write.field_tofile(field, path, append=False, attrs=None, time=None, time_units=None, time_reference=None, long_name=None, fmt='NETCDF4', keep_open=False)[source]
Module contents
Module contents
pymt.services package
Subpackages
pymt.services.constant package
Submodules
pymt.services.constant.constant module
class pymt.services.constant.constant.ConstantScalars[source]

Bases: object

Service component that returns scalars.

finalize()[source]

Clean up.

get_current_time()[source]

Component current time.

get_end_time()[source]

Component stop time.

get_grid_origin(grid_id)[source]

Origin of grid.

Parameters:grid_id (int) – Grid identifier.
Returns:origin – Origin of nodes in each dimension.
Return type:tuple
get_grid_shape(grid_id)[source]

Shape of grid.

Parameters:grid_id (int) – Grid identifier.
Returns:shape – Shape of the grid.
Return type:tuple
get_grid_spacing(grid_id)[source]

Spacing of grid.

Parameters:grid_id (int) – Grid identifier.
Returns:spacing – Spacing of nodes in each dimension.
Return type:tuple
get_input_var_names()[source]

Input variable names.

get_output_var_names()[source]

Output variable names.

get_start_time()[source]

Component start time.

get_value(name)[source]

Values on nodes of a grid.

Parameters:var (str) – Name of grid variable.
Returns:values – Values of the nodes of a grid.
Return type:ndarray
get_var_grid(var)[source]

Grid identifier for a variable.

Parameters:var (str) – Name of grid variable.
Returns:Grid identifier.
Return type:int
initialize(filename)[source]

Initialize the component from a file.

Parameters:filename (str) – Name of initialization file.
update(time)[source]

Update one time step.

update_until(time)[source]

Update until a time.

class pymt.services.constant.constant.River[source]

Bases: pymt.services.constant.constant.ConstantScalars

pymt.services.constant.river module
class pymt.services.constant.river.River[source]

Bases: pymt.services.constant.constant.ConstantScalars

Module contents
pymt.services.gridreader package
Submodules
pymt.services.gridreader.gridreader module
class pymt.services.gridreader.gridreader.TimeInterpolator[source]

Bases: object

finalize()[source]
get_current_time()[source]
get_end_time()[source]
get_grid_origin(grid_id)[source]
get_grid_shape(grid_id)[source]
get_grid_spacing(grid_id)[source]
get_input_var_names()[source]
get_output_var_names()[source]
get_start_time()[source]
get_value(name)[source]
initialize(source)[source]
update_until(time)[source]
pymt.services.gridreader.gridreader.get_abspath_or_url(filename, prefix='')[source]
pymt.services.gridreader.gridreader.read_configuration(source)[source]
pymt.services.gridreader.interpolate module
pymt.services.gridreader.interpolate.create_interpolator(fields, time_stamps, kind='linear')[source]
pymt.services.gridreader.interpolate.create_interpolators(times, fields, prefix='', kind='linear')[source]
pymt.services.gridreader.interpolate.get_field_values(fields, names)[source]
pymt.services.gridreader.interpolate.get_time_series_values(field, ordering='ascending', prefix='')[source]
pymt.services.gridreader.time_series_names module
exception pymt.services.gridreader.time_series_names.Error[source]

Bases: Exception

exception pymt.services.gridreader.time_series_names.TimeSeriesNameError(name)[source]

Bases: pymt.services.gridreader.time_series_names.Error

exception pymt.services.gridreader.time_series_names.TimeStampError(time_stamp)[source]

Bases: pymt.services.gridreader.time_series_names.Error

pymt.services.gridreader.time_series_names.extract_time_stamps_from_names(names, ordering='ascending', prefix='')[source]
pymt.services.gridreader.time_series_names.get_time_series_names(names)[source]
pymt.services.gridreader.time_series_names.sort_time_series_names(names, ordering='ascending', prefix='')[source]
pymt.services.gridreader.time_series_names.split(name)[source]
pymt.services.gridreader.time_series_names.time_stamp_as_string(time_stamp)[source]
pymt.services.gridreader.time_series_names.unsplit(name, time_stamp)[source]
Module contents
Module contents
pymt.testing package
Submodules
pymt.testing.ports module
class pymt.testing.ports.UniformRectilinearGridPort[source]

Bases: object

get_grid_origin(grid_id)[source]
get_grid_shape(grid_id)[source]
get_grid_spacing(grid_id)[source]
get_value(var_name)[source]
get_var_grid(var_name)[source]
pymt.testing.services module
Module contents
pymt.utils package
Submodules
pymt.utils.prefix module
pymt.utils.prefix.names_with_prefix(names, prefix)[source]

Find names that begin with a common prefix. In this case, names are a series .-separated words, much like module names.

Returns a list of all names that begin with prefix. The order of matched names is maintained.

>>> names_with_prefix(['foo.bar', 'foobar.baz'], 'foo')
['foo.bar']
>>> names_with_prefix(['foo.bar', 'foo.bar', 'foo.foo'], 'foo')
['foo.bar', 'foo.foo']
pymt.utils.prefix.prefix_is_empty(prefix)[source]

Check if a namespace prefix is empty.

A prefix is empty if it is None, just a “.” or an empty string.

Return True if empty, otherwise False.

pymt.utils.prefix.strip_prefix(name, prefix)[source]

Remove a prefix from a name, including any leading “.”s.

>>> strip_prefix('foo.bar', 'foo')
'bar'
>>> strip_prefix('foo.bar', '')
'foo.bar'
Module contents
Submodules
pymt.babel module

Utility functions for working with babel projects.

exception pymt.babel.BabelConfigError(prog)[source]

Bases: Exception

pymt.babel.contains_identifiers(template)[source]
pymt.babel.prepend_env_path(var, path, sep=':')[source]

Prepend a path to an environment variable.

pymt.babel.query_config_all(config='csdms-config')[source]
pymt.babel.query_config_var(var, config='csdms-config', interpolate=True)[source]

Get a configuration variable from a babel project.

pymt.babel.recursive_substitute(template, **kwds)[source]
pymt.babel.setup_babel_environ()[source]

Set up environment variables to load babelized components.

pymt.errors module
exception pymt.errors.BmiError(fname, status)[source]

Bases: pymt.errors.PymtError

exception pymt.errors.PymtError[source]

Bases: Exception

pymt.models module
pymt.timeline module

Execute events along a timeline.

Examples

>>> timeline = Timeline()
>>> timeline.add_recurring_event('event 1', 1.)
>>> timeline.add_recurring_event('event 2', .3)
>>> timeline.pop()
'event 2'
>>> timeline.pop()
'event 2'
>>> timeline.pop()
'event 2'
>>> timeline.pop()
'event 1'
>>> timeline.time
1.0
>>> for event in timeline.iter_until(2.0): print(event)
event 2
event 2
event 2
event 1
>>> timeline.pop()
'event 2'

When events occur at the same time, events are popped in as first-in, first-out.

>>> timeline = Timeline([('event 1', 1.), ('event 2', .5)])
>>> for event in timeline.iter_until(1.0): print(event)
event 2
event 1
event 2
>>> timeline = Timeline([('event 2', .5), ('event 1', 1.)])
>>> timeline.pop_until(1.05)
['event 2', 'event 1', 'event 2']
>>> timeline.time
1.05
>>> for event in timeline.iter_until(1.05): print(event)
>>> timeline.time
1.05
>>> for event in timeline.iter_until(1.06): print(event)
>>> timeline.time
1.06

The event key can be any object, even a tuple.

>>> timeline = Timeline([(('event', 2), .5), (('event', 0), 1.)])
>>> for event in timeline.iter_until(1.05): print(event)
('event', 2)
('event', 0)
('event', 2)

Events do not have to be recurring.

>>> timeline = Timeline([(('event', 2), .5), (('event', 0), 1.)])
>>> timeline.add_one_time_event('one-timer', .1)
>>> for event in timeline.iter_until(1.05): print(event)
one-timer
('event', 2)
('event', 0)
('event', 2)
class pymt.timeline.Timeline(events=None, start=0.0)[source]

Bases: object

Create a timeline of events.

Parameters:
  • events (dict-like) – Events as event-object/repeat interval pairs.
  • start (float, optional) – Start time for the timeline.

Examples

Create a timeline with two recurring events. Events can be any old object. In this case they are two strings.

>>> timeline = Timeline([('hello', 1.), ('world', 1.5)], start=3.)
>>> sorted(timeline.events) # The events are returned as a set.
['hello', 'world']

The first events will not occur at the starting time.

>>> timeline.time
3.0
>>> timeline.next_event
'hello'
>>> timeline.time_of_next_event
4.0

To advance the timeline forward to the next event, use the pop method.

>>> timeline.pop()
'hello'
>>> timeline.time
4.0
>>> timeline.pop()
'world'
>>> timeline.time
4.5

The timeline keeps track of objects, without making copies. The objects don’t even need to be hashable.

>>> hello = ['hello', 'world']
>>> timeline = Timeline([(hello, 1.)])
>>> event = timeline.pop()
>>> event is hello
True
>>> event.append('!')
>>> hello
['hello', 'world', '!']
add_one_time_event(event, time)[source]

Add an event that will only happen once.

Parameters:
  • event (event-like) – Event to add to the timeline.
  • time (float) – Time for the event to execute.

Examples

>>> timeline = Timeline()
>>> timeline.add_one_time_event('say hello', 1.)
>>> timeline.time_of_next_event
1.0
>>> timeline.pop()
'say hello'
>>> timeline.time_of_next_event  # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
IndexError: empty timeline
add_recurring_event(event, interval)[source]

Add a recurring event to the timeline.

Adds a single recurring event to the timeline. event is the event object, and interval is recurrence interval.

Parameters:
  • event (event-like) – Event to add to the timeline.
  • interval (float) – Recurrence interval of the event.

Examples

>>> timeline = Timeline()
>>> timeline.add_recurring_event('say hello', 1.)
>>> timeline.events == {'say hello'}
True
add_recurring_events(events)[source]

Add a series of recurring events to the timeline.

Adds recurring events to the timeline. events is a list where each element is tuple that gives the event object followed by the event recurrence interval.

Parameters:events (dict-like) – Events object/interval pairs to add to the timeline.

Examples

>>> timeline = Timeline()
>>> len(timeline.events)
0
>>> timeline.add_recurring_events([('hello', 1.), ('world', 1.)])
>>> sorted(timeline.events)
['hello', 'world']

Events pop as first-in, first-out.

>>> timeline.pop()
'hello'
>>> timeline.pop()
'world'

The same event can be added multiple times.

>>> timeline = Timeline()
>>> timeline.add_recurring_events([('hello', 1.), ('world', 1.),
...     ('hello', 1.)])
>>> sorted(timeline.events)
['hello', 'world']
>>> timeline.pop_until(2.)
['hello', 'world', 'hello', 'hello', 'world', 'hello']
events

All of the event objects in the timeline.

Examples

>>> timeline = Timeline([('an event', 1.), ('another event', 1.)])
>>> events = timeline.events
>>> isinstance(events, set)
True
>>> sorted(events)
['an event', 'another event']
iter_until(stop)[source]

Iterate the timeline until a given time.

Iterate the timeline until stop, popping events along the way.

Parameters:stop (float) – Time to iterate until.
Returns:The next event object as the timeline advances to stop.
Return type:event
next_event

Next event object.

Return the next event object but don’t advance the timeline forward in time.

Examples

>>> timeline = Timeline([('an event', 1.)])
>>> timeline.next_event
'an event'
>>> timeline.time
0.0
pop()[source]

Pop the next event from the timeline.

Examples

>>> timeline = Timeline(dict(hello=1.))
>>> timeline.pop()
'hello'
pop_until(stop)[source]

Advance the timeline, popping events along the way.

Advance the timeline to stop, popping events along the way. Returns a list of the event objects that were popped to advance the timeline to stop.

Parameters:stop (float) – Time to iterate until.
Returns:The events popped to get to the stop time.
Return type:list

Examples

>>> timeline = Timeline([('a', 1.), ('b', 1.), ('c', 1.)])
>>> timeline.pop_until(2.)
['a', 'b', 'c', 'a', 'b', 'c']
time

Current time along the timeline.

Examples

>>> timeline = Timeline(start=0)
>>> timeline.time
0.0
>>> timeline = Timeline(start=2)
>>> timeline.time
2.0
time_of_next_event

Time when the next event will happen.

Examples

>>> timeline = Timeline([('an event', 1.)])
>>> timeline.time_of_next_event
1.0
pymt.units module
Module contents

Miscellaneous Pages

Conda environments

conda environments is probably what you want to use for developing pymt applications.

What problem does conda environments solve? Chances are that you want to use it for other projects besides your pymt script. But the more projects you have, the more likely it is that you will be working with different versions of Python itself, or at least different versions of Python libraries. Let’s face it: quite often libraries break backwards compatibility, and it’s unlikely that any serious application will have zero dependencies. So what do you do if two or more of your projects have conflicting dependencies?

conda environments to the rescue! conda environments enables multiple side-by-side installations of Python, one for each project. It doesn’t actually install separate copies of Python, but it does provide a clever way to keep different project environments isolated.

If you are on Mac or Linux, and have conda installed, from a terminal you can run the following to create a new Python environment,

$ conda create -n myproject python

Now, whenever you want to work on a project, you only have to activate the corresponding environment. On OS X and Linux, do the following,

$ conda activate myproject

To get out of the environment,

$ conda deactivate

To remove the environment,

$ conda remove -n myproject --all

With this environment activated, you can install pymt into it with the following,

$ conda install pymt -c conda-forge

Contributing

Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.

You can contribute in many ways:

Types of Contributions

Report Bugs

Report bugs at https://github.com/csdms/pymt/issues.

If you are reporting a bug, please include:

  • Your operating system name and version.
  • Any details about your local setup that might be helpful in troubleshooting.
  • Detailed steps to reproduce the bug.

Fix Bugs

Look through the GitHub issues for bugs. Anything tagged with “bug” and “help wanted” is open to whoever wants to implement it.

Implement Features

Look through the GitHub issues for features. Anything tagged with “enhancement” and “help wanted” is open to whoever wants to implement it.

Write Documentation

pymt could always use more documentation, whether as part of the official pymt docs, in docstrings, or even on the web in blog posts, articles, and such.

Submit Feedback

The best way to send feedback is to file an issue at https://github.com/csdms/pymt/issues.

If you are proposing a feature:

  • Explain in detail how it would work.
  • Keep the scope as narrow as possible, to make it easier to implement.
  • Remember that this is a volunteer-driven project, and that contributions are welcome :)

Get Started!

Ready to contribute? Here’s how to set up pymt for local development.

  1. Fork the pymt repo on GitHub.

  2. Clone your fork locally:

    $ git clone git@github.com:your_name_here/pymt.git
    
  3. Install your local copy into a conda environment. Assuming you have conda installed, this is how you set up your fork for local development:

    $ conda create -n pymt python=3.7
    $ conda activate pymt
    $ cd pymt/
    $ conda install --file=requirements.txt
    
    $ python setup.py develop
    
  4. Create a branch for local development:

    $ git checkout -b name-of-your-bugfix-or-feature
    

    Now you can make your changes locally.

  5. When you’re done making changes, check that your changes pass flake8 and the tests:

    $ make lint
    $ make test
    

    To get flake8, just conda install it into your environment.

  6. Commit your changes and push your branch to GitHub:

    $ git add .
    $ git commit -m "Your detailed description of your changes."
    $ git push origin name-of-your-bugfix-or-feature
    
  7. Submit a pull request through the GitHub website.

Pull Request Guidelines

Before you submit a pull request, check that it meets these guidelines:

  1. The pull request should include tests.
  2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst.
  3. The pull request should work for Python 2.7, 3.6 and 3.7. Check https://travis-ci.org/csdms/pymt/pull_requests and make sure that the tests pass for all supported Python versions.

Deploying

A reminder for the maintainers on how to deploy. Make sure all your changes are committed (including an entry in HISTORY.rst). Then run:

$ git tag v<major>.<minor>.<patch>
$ git push
$ git push --tags

This will alert the pymt feedstock on conda-forge that there is a new release.

Credits

Development Leads

Contributors

  • Niels Drost
  • Tian Gan
  • Albert Kettner
  • Irina Overeem
  • Scott Stewart
  • Kang Wang

Change Log

All notable changes to landlab will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

This file was auto-generated using scripts/make_changelog.py.

Version 0.2.3

(released on 2018-09-06)

Removed

  • Removed dependency on nose

Version 0.2.2

(released on 2018-07-02)

Removed

  • Removed dependency on nose

Fixed

  • Fixed unit tests failing due to poorly named pytest fixtures.

Version 0.2.1

(released on 2018-07-01)

Removed

  • Removed dependency on nose

Fixed

  • Fixed unit tests failing due to poorly named pytest fixtures.
  • Fixed formatting so that it is strict PEP8 package-wide
  • Fixed bug in setup when creating a config file.
  • Fixed bug that used relative path for initdir.
  • Fixed coverage and upload results to coveralls.
  • Fixed continuous integration.

Added

  • Added support for “vector” grid type.
  • Added code coverage with CI.
  • Added support and testing for Python 3.
  • Added new method for discovering component plugins
  • Added grid mapper methods to components
  • Added quick_plot method to plot a 2D BMI variable
  • Added unstructured dataset to BmiCap
  • Added change log and script
  • Added plugin framework to dynamically load arbitrary components.
  • Added a “cite as” section to component metadata and docstring.
  • Added setter to change a component’s time units.

Changed

  • csdms/mdpiper/use-https [#27]
  • Use tools from the model_metadata package for metadata and staging.
  • Use Versioneer for versioning
  • Allow multiple authors of components
  • Changed to run update_until in model’s initialization folder.
  • Changed IRF methods to run from within the initialization folder
  • Use jinja templates to generate BMI docstrings.

Version 0.2

(released on 2016-12-28)

Removed

  • Removed dependency on nose

Fixed

  • Fixed unit tests failing due to poorly named pytest fixtures.
  • Fixed formatting so that it is strict PEP8 package-wide
  • Fixed bug in setup when creating a config file.
  • Fixed bug that used relative path for initdir.
  • Fixed coverage and upload results to coveralls.
  • Fixed continuous integration.

Added

  • Added support for “vector” grid type.
  • Added code coverage with CI.
  • Added support and testing for Python 3.
  • Added new method for discovering component plugins
  • Added grid mapper methods to components
  • Added quick_plot method to plot a 2D BMI variable
  • Added unstructured dataset to BmiCap
  • Added change log and script
  • Added plugin framework to dynamically load arbitrary components.
  • Added a “cite as” section to component metadata and docstring.
  • Added setter to change a component’s time units.

Changed

  • csdms/mdpiper/use-https [#27]
  • Use tools from the model_metadata package for metadata and staging.
  • Use Versioneer for versioning
  • Allow multiple authors of components
  • Changed to run update_until in model’s initialization folder.
  • Changed IRF methods to run from within the initialization folder
  • Use jinja templates to generate BMI docstrings.
  • csdms/mcflugen/fix-for-new-bmi [#8]

License

pymt is licensed under the MIT license, a short, permissive software license. Basically, you can do whatever you want as long as you include the original copyright and license notice in any copy of the software/source.

License Text

The MIT License (MIT)

Copyright (c) 2014 Community Surface Dynamics Modeling System

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Help

If you encounter any problems when using pymt, please visit us at the CSDMS Help Desk and explain what occurred. Or, if you’re developing with pymt feel free to open an issue in the pymt GitHub repository.

Indices and tables