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()

pymt is an element of the CSDMS Workbench, an integrated system of software tools, technologies, and standards for building and coupling models.

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.

PYMT

The Python Modeling Toolkit (pymt)

Build Status License Code Style Documentation Status Coverage Status Conda Version Conda Installation Conda Downloads 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

What does it look like? Here is an example of a simple pymt program that couples a Waves model with a Coastline Evolution model.

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()

pymt is an element of the CSDMS Workbench, an integrated system of software tools, technologies, and standards for building and coupling models.

This work is 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/mamba

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

Once you’ve installed conda, we suggest installing mamba to install additional packages.

$ conda install mamba -c conda-forge

Install pymt

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

$ mamba 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 installed by default with pymt.

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

>>> import pymt
>>> pymt.MODELS
{'Child', 'FrostNumber', 'Ku', 'Cem', 'Waves', 'Sedflux3D', 'Plume', 'Subside', 'Hydrotrend', 'Avulsion'}

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

Run a model

Create an instance of the Hydrotrend model through pymt:

>>> model = pymt.MODELS.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'

Here, ‘d’ is short for ‘days’.

The Hydrotrend model exposes a set of output variables, as shown by the output_var_names property:

>>> for var in model.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:

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

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

>>> model.var_units(var_name)
'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(var_name)
...     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 pair of more detailed Jupyter Notebook examples of using Hydrotrend can be found in the Examples section. 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 the Anaconda scientific computing environment. If you don’t have it installed, the Anaconda installation guide can help you through the process.

Once you’ve installed Anaconda, we suggest using the mamba package manager. mamba is pretty much the same as conda, only faster. If you would rather stick with conda, just replace occurrences of mamba with conda.

$ conda install mamba -c conda-forge

Add the conda-forge channel to the list of enabled conda channels on your machine:

$ mamba 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:

$ mamba create -n pymt python=3

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

$ conda activate pymt

Install pymt into this conda environment with:

$ mamba install pymt

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

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

>>> import pymt

A default set of models is included in the pymt install:

>>> for model in pymt.MODELS:
...     print(model)
...
Avulsion
Plume
Sedflux3D
Subside
FrostNumber
Ku
Hydrotrend
Child
Cem
Waves

From source

We strongly recommend using the Anaconda scientific computing environment. If you don’t have it installed, the Anaconda installation guide can help you through the process.

Once you’ve installed Anaconda, we suggest using the mamba package manager. mamba is pretty much the same as conda, only faster. If you would rather stick with conda, just replace occurrences of mamba with conda.

$ conda install mamba -c conda-forge

Add the conda-forge channel to the list of enabled conda channels on your machine:

$ mamba 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:

$ mamba create -n pymt python=3

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

$ conda activate pymt

The source code for pymt can be accessed from its Github repository.

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
$ tar -xf master

Once you have a copy of the source, change into the source directory and install the dependencies required by pymt into the conda environment you created above:

$ mamba install --file=requirements.txt

Then install pymt with:

$ pip install -e .

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

>>> import pymt

A default set of models is included in the pymt install:

>>> for model in pymt.MODELS:
...     print(model)
...
Avulsion
Plume
Sedflux3D
Subside
FrostNumber
Ku
Hydrotrend
Child
Cem
Waves

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:

$ mamba install pymt_cem -c conda-forge

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 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 Components

Data Components

The following table lists the data components currently available through pymt.

Component

Summary

GeoTiff

Access data and metadata from a GeoTIFF file, through either a local filepath or a remote URL.

GridMET

Fetch and cache gridMET meteorological data.

NWIS

Download the National Water Information System (Nwis) time series datasets.

NWM

Download the National Water Model datasets.

SoilGrids

Download the soil property datasets from the SoilGrids system.

Topography

Fetch and cache NASA Shuttle Radar Topography Mission (SRTM) land elevation data using the OpenTopography REST API.

Model Components

The following table lists the model components currently available through pymt.

Component

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

Notebook

Run on Binder…

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

Notebook

Run on Binder…

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://bmi.readthedocs.io 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 community-led collection of recipes, build infrastructure, and distributions for the conda package manager. 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.

CSDMS

See Community Surface Dynamics Modeling System (CSDMS).

CSDMS Workbench

An integrated system of software tools, technologies, and standards for building and coupling models. See https://csdms.colorado.edu/wiki/Workbench for more information.

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.

Jupyter Notebook

Jupyter Notebook is an open-source web application for creating and sharing documents that contain live code, equations, visualizations, and narrative text. See https://jupyter.org/.

mamba

A faster, open-source, alternative to the conda package manager. See https://mamba.readthedocs.io.

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: Error

Exception to indicate a bad input/output variable name

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() 
{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') 
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.) 
{name: air_port, status: running, time: 1.0}
...
{name: air_port, status: running, time: 10.0}
>>> comp.current_time
10.0
>>> comp.run(101.) 
Traceback (most recent call last):
ValueError: AirPort
>>> comp.current_time
10.0
>>> comp.run(100.) 
{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: 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.

property current_time

Current time for component updating.

property 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

property 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.

property start_time

Start time for component updating.

property time_step

Component time step.

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

property 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:
...     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().__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]
property input_items

Input item names as a list.

property name

Name of the wrapped component.

property 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:
...     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:
...     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:
...     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:
...     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

property components

Names of the components.

property driver

Name of the driver component.

property 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() 
{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:
...     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.

property 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: 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

Bridge between BMI and a PyMT component.

class pymt.framework.bmi_bridge.BmiCap[source]

Bases: GridMapperMixIn, _BmiCap, BmiTimeInterpolator, SetupMixIn

class pymt.framework.bmi_bridge.DataValues(bmi, name)[source]

Bases: object

property data
property grid
property intent
property location
property name
property size
property type
property units
values(**kwds)[source]
class pymt.framework.bmi_bridge.DeprecatedMethods[source]

Bases: object

get_grid_dim(grid, dim)[source]
get_grid_face_node_connectivity(grid, out=None)[source]
get_grid_face_node_offset(grid, out=None)[source]
get_grid_face_nodes(grid, out=None)[source]
get_grid_ndim(grid)[source]
get_grid_nodes_per_face(grid, out=None)[source]
get_grid_number_of_edges(grid)[source]
get_grid_number_of_faces(grid)[source]
get_grid_number_of_nodes(grid)[source]
get_grid_number_of_vertices(grid)[source]
get_grid_origin(grid, out=None)[source]
get_grid_rank(grid)[source]
get_grid_shape(grid, out=None)[source]
get_grid_size(grid)[source]
get_grid_spacing(grid, out=None)[source]
get_grid_type(grid)[source]
get_grid_x(grid, out=None)[source]
get_grid_y(grid, out=None)[source]
get_grid_z(grid, out=None)[source]
get_var_grid(name)[source]
get_var_grid_loc(name)[source]
get_var_intent(name)[source]
get_var_itemsize(name)[source]
get_var_location(name)[source]
get_var_nbytes(name)[source]
get_var_type(name)[source]
get_var_units(name)[source]
pymt.framework.bmi_bridge.bmi_factory(cls)[source]
pymt.framework.bmi_docstring module
pymt.framework.bmi_docstring.bmi_docstring(plugin, author=None, version=None, license=None, doi=None, url=None, parameters=None, summary=None, cite_as=None, email=None)[source]

Build the docstring for a BMI model.

Parameters:
  • name (str) – Name of a BMI component.

  • author (str, optional) – Name of author or authors.

  • version (str, optional) – Version string for the component.

  • license (str, optional) – Name of the license of the component.

  • doi (str, optional) – A DOI for the component.

  • url (str, optional) – URL of the component’s location on the internet.

  • parameters (iterable, optional) – List of input parameters for the component. Each parameter object must have attributes for name, type, value, units, and desc.

  • cite_as (iterable of str, optional) – List of citations for this component.

  • email (str, optional) – Contact email address.

Returns:

The docstring.

Return type:

str

Examples

>>> from pymt.framework.bmi_docstring import bmi_docstring
>>> print(bmi_docstring('Model', author='Walt Disney')) 
Basic Model Interface for Model.
...
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_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

property author
property cite_as
property contact
property datadir
property defaults
property doi
property email
property license
property 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

property summary
property url
property 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
class pymt.framework.bmi_ugrid.Points(*args)[source]

Bases: _Base

class pymt.framework.bmi_ugrid.Rectilinear(*args)[source]

Bases: _Base

class pymt.framework.bmi_ugrid.Scalar(*args)[source]

Bases: _Base

class pymt.framework.bmi_ugrid.StructuredQuadrilateral(*args)[source]

Bases: _Base

class pymt.framework.bmi_ugrid.UniformRectilinear(*args)[source]

Bases: _Base

class pymt.framework.bmi_ugrid.Unstructured(*args)[source]

Bases: _Base

class pymt.framework.bmi_ugrid.Vector(*args)[source]

Bases: _Base

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.

property fill_value

Value to use when interpolating values outside of the data.

interpolate(time)[source]

Interpolate the data at a given time.

property maxsize

The maximum number of times to be stored.

property 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 
[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

This module is not available (no ESMF installation was found)

class pymt.grids.esmp.EsmpField(*args, **kwargs)[source]

Bases: 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: IGrid

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

Bases: EsmpUniformRectilinear, EsmpRectilinearField

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

Bases: Rectilinear, EsmpGrid

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

Bases: EsmpRectilinear, EsmpStructuredField

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

Bases: Structured, EsmpGrid

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

Bases: EsmpStructured, EsmpField

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

Bases: UniformRectilinear, EsmpStructured

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

Bases: Unstructured, EsmpGrid

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

Bases: EsmpUnstructured, 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: Unstructured, 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: UniformRectilinear, 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') 
Traceback (most recent call last):
    ...
DimensionError: 2 != 6
>>> data = np.ones ((3, 2))
>>> g.add_field ('bad var', data, centering='point') 
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') 
Traceback (most recent call last):
    ...
DimensionError: (2, 1) != (1, 2)
>>> data = np.arange(3)
>>> g.add_field('bad var', data, centering='zonal') 
Traceback (most recent call last):
    ...
DimensionError: 3 != 2
>>> data = np.array(3)
>>> g.add_field('bad var', data, centering='zonal')  
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: Rectilinear, StructuredField

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

Bases: Structured, GridField

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

Bases: 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: GridType

class pymt.grids.grid_type.GridTypeStructured[source]

Bases: GridType

class pymt.grids.grid_type.GridTypeUnstructured[source]

Bases: GridType

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

Bases: Error

Error to indicate an invalid value for value centering.

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

Bases: 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: Error

class pymt.grids.igrid.IField[source]

Bases: 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: GridTypeError

Error to indicate a grid is not a structured grid

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

Bases: GridTypeError

Error to indicate a grid is not a uniform rectilinear grid

type = 'uniform rectilinear'
pymt.grids.map module
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: UniformRectilinearPoints, 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: 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: RectilinearPoints, 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: 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: StructuredPoints, 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: 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: 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: 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
exception pymt.grids.DimensionError(dim0, dim1)[source]

Bases: Error

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

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

Bases: UniformRectilinear, 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') 
Traceback (most recent call last):
    ...
DimensionError: 2 != 6
>>> data = np.ones ((3, 2))
>>> g.add_field ('bad var', data, centering='point') 
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') 
Traceback (most recent call last):
    ...
DimensionError: (2, 1) != (1, 2)
>>> data = np.arange(3)
>>> g.add_field('bad var', data, centering='zonal') 
Traceback (most recent call last):
    ...
DimensionError: 3 != 2
>>> data = np.array(3)
>>> g.add_field('bad var', data, centering='zonal')  
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.Rectilinear(*args, **kwds)[source]

Bases: RectilinearPoints, 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.RectilinearField(*args, **kwds)[source]

Bases: Rectilinear, StructuredField

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

Bases: 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: StructuredPoints, 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.StructuredField(*args, **kwds)[source]

Bases: Structured, GridField

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

Bases: 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.UniformRectilinear(shape, spacing, origin, **kwds)[source]

Bases: UniformRectilinearPoints, 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: RectilinearPoints

get_origin()[source]

Coordinates of the grid’s lower-left corner

get_spacing()[source]

Spacing between nodes in each direction

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

Bases: 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.UnstructuredField(*args, **kwargs)[source]

Bases: GridField

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

Bases: 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.is_rectilinear(grid, strict=True)[source]
pymt.grids.is_structured(grid, strict=True)[source]
pymt.grids.is_uniform_rectilinear(grid)[source]
pymt.grids.is_unstructured(grid, strict=True)[source]
pymt.mappers package
Submodules
pymt.mappers.celltopoint module
class pymt.mappers.celltopoint.CellToPoint[source]

Bases: IGridMapper

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

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

property 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: EsmpMapper

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

Bases: 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.

property 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: 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: 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: 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: IGridMapper

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

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

property 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: 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.

property 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
class pymt.mappers.CellToPoint[source]

Bases: IGridMapper

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

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

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

Map values on the source grid to the destination grid.

static test(dst_grid, src_grid)[source]
exception pymt.mappers.IncompatibleGridError(dst, src)[source]

Bases: MapperError

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

class pymt.mappers.NearestVal[source]

Bases: 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.

property 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: IGridMapper

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

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

property 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.find_mapper(dst_grid, src_grid)[source]

Find appropriate mappers to map bewteen two grid-like objects

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

Bases: PortPrinter

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

Bases: object

close()[source]
property 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]
property var_name
write()[source]
pymt.portprinter.utils module
exception pymt.portprinter.utils.BadFileFormatError(fmt)[source]

Bases: Error

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

Bases: 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: 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]
property face_connectivity
property face_count
property face_data_dimensions
property face_node_connectivity
property field
property field_axes
has_dimension(name)[source]
has_variable(name)[source]
property node_coordinates
property node_count
property node_data_dimensions
property root
set_variable(name, *args, **kwds)[source]
property time_count
property topology_dimension
property type
property vertex_count
class pymt.printers.nc.ugrid.NetcdfRectilinearField(path, field, fmt='NETCDF4', append=False, time=None, keep_open=False)[source]

Bases: NetcdfField

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

Bases: NetcdfRectilinearField

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

Bases: NetcdfStructuredField

property face_data_dimensions
property node_coordinates
property node_data_dimensions
property topology_dimension
property 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]
property fields
is_variable_data(name)[source]
property time
property times
variable_data(name)[source]
variable_data_names()[source]
class pymt.printers.nc.ugrid_read.NetcdfRectilinearFieldReader(path, fmt='NETCDF4')[source]

Bases: NetcdfFieldReader

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

Bases: NetcdfFieldReader

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

Bases: 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: ConstantScalars

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

Bases: 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: Error

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

Bases: 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
class pymt.testing.services.AirPort[source]

Bases: EmptyPort

class pymt.testing.services.EarthPort[source]

Bases: EmptyPort

class pymt.testing.services.EmptyPort[source]

Bases: UniformRectilinearPoints

property current_time
property end_time
finalize()[source]
get_component_name()[source]
get_grid_origin(grid_id)[source]
get_grid_shape(grid_id)[source]
get_grid_spacing(grid_id)[source]
get_value(var_name, units=None)[source]
get_var_grid(var_name)[source]
get_var_units(var_name)[source]
initialize()[source]
run(time)[source]
set_value(var_name, values)[source]
property start_time
property time_step
class pymt.testing.services.WaterPort[source]

Bases: EmptyPort

pymt.testing.services.get_class(name)[source]
pymt.testing.services.get_class_names()[source]
pymt.testing.services.get_instance(name)[source]
pymt.testing.services.instantiate(cls, name)[source]
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'
pymt.utils.utils module
pymt.utils.utils.as_cwd(path)[source]
pymt.utils.utils.suppress_stdout()[source]
Module contents
pymt.utils.as_cwd(path)[source]
pymt.utils.err(message: Any | None = None, file: IO | None = None, nl: bool = True, *, err: bool = True, color: bool | None = None, **styles: Any) None

This function combines echo() and style() into one call. As such the following two calls are the same:

click.secho('Hello World!', fg='green')
click.echo(click.style('Hello World!', fg='green'))

All keyword arguments are forwarded to the underlying functions depending on which one they go with.

Non-string types will be converted to str. However, bytes are passed directly to echo() without applying style. If you want to style bytes that represent text, call bytes.decode() first.

Changed in version 8.0: A non-string message is converted to a string. Bytes are passed through without style applied.

New in version 2.0.

pymt.utils.out(message: Any | None = None, file: IO | None = None, nl: bool = True, *, err: bool = True, color: bool | None = None, **styles: Any) None

This function combines echo() and style() into one call. As such the following two calls are the same:

click.secho('Hello World!', fg='green')
click.echo(click.style('Hello World!', fg='green'))

All keyword arguments are forwarded to the underlying functions depending on which one they go with.

Non-string types will be converted to str. However, bytes are passed directly to echo() without applying style. If you want to style bytes that represent text, call bytes.decode() first.

Changed in version 8.0: A non-string message is converted to a string. Bytes are passed through without style applied.

New in version 2.0.

Submodules
pymt.errors module
exception pymt.errors.BadUnitError(unit)[source]

Bases: PymtError

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

Bases: PymtError

exception pymt.errors.IncompatibleUnitsError(src, dst)[source]

Bases: PymtError

exception pymt.errors.PymtError[source]

Bases: Exception

pymt.model_collection module
class pymt.model_collection.ModelCollection[source]

Bases: object

property errors
items()[source]
keys()[source]
static load_entry_point(entry_point)[source]
values()[source]
exception pymt.model_collection.ModelLoadError(name, reason=None)[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  
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']
property 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

property 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']
property time

Current time along the timeline.

Examples

>>> timeline = Timeline(start=0)
>>> timeline.time
0.0
>>> timeline = Timeline(start=2)
>>> timeline.time
2.0
property 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
pymt.units.transform_azimuth_to_math(angle, units='rad')[source]
pymt.units.transform_math_to_azimuth(angle, units='rad')[source]
Module contents
class pymt.UnitSystem(filepath=None)

Bases: _UnitSystem

A system of units.

A unit-system is a set of units that are all defined in terms of the same set of base units. In the SI system of units, for example, the base units are the meter, kilogram, second, ampere, kelvin, mole, and candela. (For definitions of these base units, see http://physics.nist.gov/cuu/Units/current.html)

In the UDUNITS-2 package, every accessible unit belongs to one and only one unit-system. It is not possible to convert numeric values between units of different unit-systems. Similarly, units belonging to different unit-systems always compare unequal.

Parameters:

filepath (str, optional) – Path to a udunits2 xml-formatted unit database. If not provided, a default system of units is used.

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 mamba installed, from a terminal you can run the following to create a new Python environment,

$ mamba 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,

$ mamba activate myproject

To get out of the environment,

$ conda deactivate

To remove the environment,

$ mamba remove -n myproject --all

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

$ mamba 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
    
    $ pip install -e .
    
  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

  • Mike Taves

  • Kang Wang

Release Notes

1.3.1 (2021-03-18)

Documentation Enhancements

  • Added text on the CSDMS Workbench to the README and docs. (#129)

Other Changes and Additions

  • Added GitHub actions for continuous integration, building and testing on all platforms and Python 3.7+. (#132)

  • Removed pymt.udunits in favor of gimli.units for the parsing and converting of units. (#133)

  • Added GitHub Actions workflow to test notebooks, for Linux and Mac with Python 3.9. (#133)

  • Added GitHub Actions workflow to build the docs. (#134)

1.3.0 (2020-10-21)

New Features

  • Added ModelCollection class and MODELS instance to hold the currently loaded models. (#128)

Bug Fixes

  • Fixed an issue in quick_plot when trying to plot unstructured meshes. (#127)

1.2.1 (2020-09-22)

Bug Fixes

  • Fixed model metadata discovery by using the model_metadata package to look for metadata files. (#125)

1.2.0 (2020-09-11)

New Features

  • Added a cythonized udunits2 module. (#120)

Other Changes and Additions

  • Use micromamba and mamba in place of conda and miniconda for our CI both on Travis and AppVeyor. mamba is significantly faster than conda is Open Source. (#124)

1.1.3 (2020-04-23)

Documentation Enhancements

  • Updated the pymt example notebooks. (#112)

  • Updated the README file for the notebooks. (#114)

Other Changes and Additions

  • Included the cfunits xml data with the pymt installation. (#113)

1.1.2 (2020-04-08)

Documentation Enhancements

  • Fixed build of pymt documentation on readthedocs.io. (#110)

Other Changes and Additions

  • Changed behavior of grid_x, grid_y, and grid_z for rectilinear grids (as described in csdms/bmi#65). These functions now return, respectively, a vector of length number of columns, number of rows, and number of z-levels, not a vector of length number of nodes. (#107)

  • Removed deployment of pymt to PyPI. (#111)

1.1.0 (2020-02-26)

New Tutorial Notebooks

  • Added a new notebook for the ECSimpleShow model. (#96)

New Features

  • Added the SensibleBMI class that provides a user-centric interface to a BMI component. (#86)

  • Added support for the BMI structured_quadrilateral grid type. (#89)

  • Added support for the BMI rectilinear grid type. (#90)

Bug Fixes

  • Fixed issues with the sedflux and Child notebooks. (#94)

Documentation Enhancements

  • Added Binder to pymt documentation. (#97)

  • Added a table of all models available from pymt. Rows contain a summary of the model and a link to a notebook, if available, that demonstrates how to use the model. The links are to both a binder as well as a static html page of the notebook. (#99)

  • Fixed broken links in the documentation. (#100)

  • Added links in the documentation to the CSDMS Help Desk. (#103)

  • Updated the Github links in the example notebooks. (#105)

Other Changes and Additions

  • Fixed some failing unit tests. (#93)

1.0.3 (2019-05-15)

Other Changes and Additions

  • Included a copy of cfunits package as part of pymt. (#85)

1.0.2 (2019-05-14)

Bug Fixes

  • Fixed an error getting the metadata path from BMI class. (#83)

  • Fixed a cfunits import error on Windows. (#84)

1.0.1 (2019-05-13)

Bug Fixes

  • Fixed an incorrect path from METADATA attribute. (#82)

1.0.0 (2019-02-18)

  • Added a more pythonic BMI (#55)

  • Remove support from Python 2.7

  • Fixed CEM notebook (#64)

  • Fixed int error on some platforms (#58)

  • Improved documentation

  • Improved tests

0.2.9 (2019-02-09)

  • Fixed the quickstart tutorial (#55)

  • Removed the old way of loading models (i.e. from a package called csdms) (#54)

0.2.8 (2019-02-07)

  • Code clean-up (#50, #52)

  • Improved the HydroTrend notebook

  • Added continuous integration on Windows using AppVeyor (#48)

0.2.7 (2019-01-23)

  • Fixed installation issue where tests folder was installed (#43)

  • Removed utility scripts from installation (#42)

  • Make installation of ESMF optional (#41)

  • Added pymt example notebooks to docs (#40)

  • Improved documentation

0.2.6 (2018-10-24)

  • Load pymt plugins as components (#38)

0.2.5 (2018-10-04)

  • Fixed for new model_metadata API (#36)

0.2.4 (2018-09-07)

  • Improved documentation

  • Improved continuous integration

0.2.3 (2018-07-06)

  • Removed dependency on nose

0.2.2 (2018-07-02)

  • Removed dependency on nose

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

0.2.1 (2018-07-01)

  • Removed dependency on nose

  • 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 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.

  • 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.

0.2.0 (2016-12-28)

  • Removed dependency on nose

  • 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 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.

  • 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

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