2. Python¶
2.1. Plugin Specific Third-party Dependencies¶
The Python plugin requires the following third-party libraries/tools to function:
Python and other third-party modules that will be used.
2.2. Building GeoGate with Python Plugin Support¶
To build the Catalyst plugin, the user needs to provide the -DGEOGATE_USE_PYTHON=ON CMake option at build time. Otherwise, GeoGate will not build with Python plugin support.
2.3. Runtime Configuration Options¶
In GeoGate, each specific plugin comes with its own set of runtime configuration options. For the Python plugin, users can specify the following options:
PythonScripts: This option allows users to provide a list of Python scripts, which can be used to process or generate data. The list can be provided as a double-column-separated list like
"scriptA.py:scriptB.py".
The GeoGate can create its own export state, which is the basic data object utilized by the ESMF library for exchanging data among model components. In this scenario, users must provide the following additional run-time configuration options.
Note
More information about the ESMF State class can be found in the ESMF reference manual.
ExportMeshFile: This refers to the ESMF mesh file that will be utilized to create the underlying mesh for the ESMF fields attached to the ESMF export state.
ExportFields: This refers to the list of export fields that will be created on the GeoGate export state. You can provide the list in one of two formats: as a double-column-separated list (e.g., “fieldA:fieldB”) or as a YAML-formatted list (e.g., [fieldA, fieldB]), which is applicable if you are using ESMX as a driver component.
Note
ESMF supports a custom unstructured grid file format for describing meshes. This format is more compatible than the SCRIP format with the methods used to create an ESMF Mesh object, which reduces the amount of conversion required to create a Mesh. For more information about the format of the ESMF Mesh file, refer to the ESMF reference documentation.
2.4. Interacting with Python¶
The interaction with the Python script is primarily managed by the Conduit library. The GeoGate generic data component is implemented in Fortran, a programming language that does not support direct interaction with Python. Consequently, any data transferred from GeoGate to Python, or data generated by the Python script that must be sent back to GeoGate, must traverse multiple programming layers written in different languages, including Fortran, C/C++, and Python.
The Conduit library provides an API that supports Fortran, C/C++, and Python to describe hierarchal data using a JSON-inspired data model and a dynamic API for rapid construction and consumption of hierarchical objects.
To access the nodes provided by the GeoGate, the user needs to use the Conduit Python module that is explained in The Conduit Python Tutorial.
2.4.1. Import: Data consumed by Python¶
The Conduit node named my_node can be accessed from Python to process data provided by the GeoGate. Please refer to the Conduit User Guide for more information about the Conduit nodes.
The my_node includes the following information in a hierarchical way:
2.4.2. Export: Data produced by Python¶
The Conduit node named my_node_return can be accessed from Python to provide data to GeoGate and update the fields in its export state. To access a specific field in the GeoGate export state, the following example statement my_node_return['data/fields/fieldA/values'] can be used.
2.5. Limitations¶
Running Python scripts in parallel can be challenging. To address this, users can allocate a single core in the runtime configuration file to the GeoGate component, which will facilitate the straightforward initiation of the Python script.
The GeoGate component provides MPI_COMM_WORLD as the mpi/comm node, along with additional information such as the processor ID (mpi/localpet) and the total number of processors (mpi/petcount) utilized by the component. This information is accessible in both Fortran and Python through the my_node Conduit node, and users can access this data using the mpi4py Python module for parallel data processing.
At this time, GeoGate does not provide information about the decomposition used by the component. However, this information could be added to the my_node Conduit node if needed.
2.6. Example Python Scripts¶
To save Conduit nodes provided by the GeoGate, the following simple Python script can be used:
import conduit
from conduit import Node
# Arguments
channel = "atm"
debug = True
# Access to channel data
my_channel = my_node["channels/{}".format(channel)]
# Save the data in the channel
if debug:
my_channel.save('my_channel')
The following Python code can be used to read node data from a file:
from conduit import Node
# Arguments
channel = "atm"
data_dir = './data'
my_channel = Node()
my_channel.load(os.path.join(data_dir, 'my_channel_{}".format(channel)))
The following example creates plots using data provided by the GeoGate:
import os
import conduit
from conduit import Node
import xarray as xr
import cartopy.crs as ccrs
import matplotlib as mpl
import matplotlib.pyplot as plt
# Arguments
channel = "ocn"
debug = True
nx_ocn = 1440
ny_ocn = 721
# Access to channel data
my_channel = my_node["channels/{}".format(channel)]
ds = xr.Dataset(
data_vars = {
"mask": (["lat", "lon"], my_channel['data/mask/values/face_mask'].reshape((ny_ocn,nx_ocn))),
"So_t": (["lat", "lon"], my_channel['data/fields/So_t/values'].reshape((ny_ocn,nx_ocn)))
},
coords = {
"lon": (["lat", "lon"], my_channel['data/coords/values/face_lon'].reshape((ny_ocn,nx_ocn))),
"lat": (["lat", "lon"], my_channel['data/coords/values/face_lat'].reshape((ny_ocn,nx_ocn))),
}
)
fig, axis = plt.subplots(1, 1, subplot_kw=dict(projection=ccrs.PlateCarree(central_longitude=0.0, globe=None)))
ds["So_t"].where(ds.mask == 0).plot(
ax=axis,
transform=ccrs.PlateCarree(),
cbar_kwargs={"orientation": "horizontal", "shrink": 0.7},
robust=True,
)
axis.coastlines()
fig, axis = plt.subplots(1, 1, subplot_kw=dict(projection=ccrs.Orthographic(-90, 30)))
ds["So_t"].where(ds.mask == 0).plot(
ax=axis,
transform=ccrs.PlateCarree(),
cbar_kwargs={"orientation": "horizontal", "shrink": 0.7},
robust=True,
)
axis.coastlines()