Basics
This is a basic introduction to using pyarts
It will take you through the following concepts:
Create a workspace
This example shows how to create a Workspace, the common entry point for all pyarts simulations.
# The first step is to import the pyarts package. This will make all
# pyarts modules available to you.
import pyarts3 as pyarts
# The Workspace class is the common entry point for all pyarts simulations.
# It is used to interface with the ARTS C++ library and to manage the
# simulation state.
ws = pyarts.Workspace()
# That's it. You have created a Workspace. You can now use it to run
# simulations. For example, you can run the ARTS Hello World example:
print("Hello, World!\n", ws)
Setting workspace variable
This example shows how to set a workspace variable. The way workspace variables are set depends on the constructors or __init__ methods available for the respective ARTS classes. We hope that most of our constructors make pythonic sense
# Import the module
import numpy as np # For some of the examples
import pyarts3 as pyarts
# Create a workspace
ws = pyarts.Workspace()
"""
Indices can be set from the built-in python int.
It is necessary to create an index object first, since the workspace
variable must know the type.
"""
ws.ind = pyarts.arts.Index(1)
print("Should contain 1: ", ws.ind)
"""
Once an index exist on the workspace, you can set it directly from int.
"""
ws.ind = 2
print("Should contain 2: ", ws.ind)
"""
What follows are some examples of how to set other types of workspace
variables. The general rule is that you can set a workspace variable
from any python object that has a corresponding ARTS type. For
example, you can set a string from a python string, a matrix from a
numpy array, etc.
"""
# Numeric
ws.num = pyarts.arts.Numeric(9.81) # from builtin float
print("Should contain 9.81: ", ws.num)
ws.num = 10 # from builtin int
print("Should contain 10: ", ws.num)
ws.num = np.float64(9.81) # from numpy float
print("Should contain 9.81, again: ", ws.num)
# Numeric
ws.str = pyarts.arts.String("hello") # from builtin str
print("Should contain 'hello': ", ws.str)
ws.str = b"ARTS" # from bytes
print("Should contain 'ARTS': ", ws.str)
# Vector
ws.vec = pyarts.arts.Vector([1, 2, 3]) # from builtin list
print("Should contain 1 2 3: ", ws.vec)
ws.vec = np.array([4, 5, 6]) # from numpy array
print("Should contain 4 5 6: ", ws.vec)
# Matrix
ws.mat = pyarts.arts.Matrix([[1, 2], [3, 4]]) # from builtin list
print("Should contain\n 1 2\n3 4:\n", ws.mat)
ws.mat = np.array([[5, 6], [7, 8]]) # from numpy array
print("Should contain\n 5 6\n7 8:\n", ws.mat)
"""
Many more types are supported. Please look at the documentation of the
respective Workspace Group for more information on how to initialize them.
"""
# TESTING
# AS THIS FILE IS RUN TO TEST ARTS, WE NEED TO CHECK THAT
# THE CONTENT OF THE VARIABLES ARE GOOD.
assert np.isclose(ws.ind, 2)
assert np.isclose(ws.num, 9.81)
assert np.allclose(ws.vec, [4, 5, 6])
assert np.allclose(ws.mat, [[5, 6], [7, 8]])
# END TESTING
Loading data from file
This example shows how to load data from a file into a workspace variable.
# Import the module
import pyarts3 as pyarts
"""
ARTS relies heavily on data provided by two catalogs: arts-xml-data and
arts-cat-data, they provide absorption lines, atmospheric profiles,
and other data.
The download method automatically retrieves the correct catalogs for
your pyarts version. It also sets the search paths described below
correctly. The method should always be called at the beginning of
your script right after importing pyarts. It will only download
the catalogs if they are not already present. But it is still
important to call it, since it will set the search paths correctly.
By default, the catalogs are stored in your home directory in the
`~/.cache/arts/` folder.
"""
pyarts.data.download()
# Create a workspace
ws = pyarts.Workspace()
"""
Before we load data into a workspace variable, we need to know about
one of the tricks that ARTS uses to make the file IO more flexible.
The trick is that ARTS does not just look for files in the folder
that you specify, but also in a number of other folders. This is
useful since a lot of radiative transfer data is the same regardless
of the scenario that you are simulating. For example, the absorption
lines of H2O are the same regardless of whether you are simulating
a clear sky or a cloudy sky.
The folders that ARTS looks in are called search paths. You can
print the search paths that ARTS uses by doing:
"""
print("ARTS search paths:", pyarts.arts.globals.parameters.datapath)
"""
The results of this command will depend on your environment variables
at the time of first import of pyarts during the scripting. The default
search paths can be changed by setting the ARTS_DATA_PATH environment
variable. For example, if you want to add a folder called "my_data"
to the search paths, you can do:
export ARTS_DATA_PATH=/my_data
before starting python. If you want to add multiple folders, you can
separate them with a colon:
export ARTS_DATA_PATH=/my_data:/my_other_data
Check the documentation for your shell if you want to make this change
permanent.
It is always possible to add additional search paths from within python:
"""
pyarts.arts.globals.parameters.datapath.append("/my_data")
print("ARTS search paths:", pyarts.arts.globals.parameters.datapath)
"""
There are different ways that you can load data from a file into
the workspace. There is no "best" way to do this, it depends on the
context, and what you find most readable.
"""
# Call the WorkspaceVariable member method "readxml" to load data from file
ws.absorption_bands.readxml("lines/O2-66.xml")
# TESTING
# AS THIS FILE IS RUN TO TEST ARTS, WE NEED TO CHECK THAT
# THE CONTENT OF THE VARIABLES ARE GOOD.
assert len(ws.absorption_bands) > 0
assert "/my_data" in pyarts.arts.globals.parameters.datapath
# END TESTING
Running a workspace method
This example demonstrates how to run a workspace method. We have shown this in previous examples, but here we will explain some details.
# Import the module
import pyarts3 as pyarts
# Create a workspace
ws = pyarts.Workspace()
"""
All workspace methods can take pure python instance or workspace variables
"""
example_index = pyarts.arts.Index(1)
ws.example_index = example_index
print(example_index)
print(ws.example_index)
print(type(ws.example_index), type(example_index))
"""
You can call workspace methods with named or positional arguments or any
combination thereof that python accepts
"""
# 1) Name some arguments
ws.spectral_radiance_space_agendaSet(option="UniformCosmicBackground")
# 2) Name some arguments, use positional for the others
ws.spectral_radiance_space_agendaSet(
ws.spectral_radiance_space_agenda,
option="UniformCosmicBackground",
)
# 3) Name all arguments
ws.spectral_radiance_space_agendaSet(
spectral_radiance_space_agenda=ws.spectral_radiance_space_agenda,
option="UniformCosmicBackground",
)
# 4) Use all positional arguments
ws.spectral_radiance_space_agendaSet(
ws.spectral_radiance_space_agenda, "UniformCosmicBackground"
)
Create an agenda
This will explain how to create an agenda and set it on the workspace.
# Import the module
import pyarts3 as pyarts
# Create a workspace
ws = pyarts.Workspace()
"""
Agendas are a collection of functions that define the simulation
of some core component. For example, the iy_space_agenda defines
how the radiative transfer equation receives radiation from a
background of space --- commonly just the cosmic background radiation.
These Agendas are defined from a set of common inputs and outputs.
Agendas must consist of methods that combined covers the inputs and
outputs of the agenda itself. While it is possible to create an
agenda manually, it is much more preferable to use the workspace
methods that exist to create the agenda for you.
Before showing you how to creating your own iy_space_agenda,
this method call can do it for you, and it will probably do
it faster and safer than any manual approach:
"""
ws.spectral_radiance_space_agendaSet(option="UniformCosmicBackground")
"""
That said, we provide interpreted ways to create agendas manually.
The cosmic background radiation agenda of the method call above
can be created by the following, decorated code:
"""
@pyarts.workspace.arts_agenda
def cosmic_background(ws):
ws.spectral_radianceUniformCosmicBackground(
spectral_radiance=ws.spectral_radiance,
frequency_grid=ws.frequency_grid,
)
ws.spectral_radiance_jacobianEmpty()
ws.Ignore(ws.ray_path_point)
ws.spectral_radiance_space_agenda = cosmic_background
print(cosmic_background)
print(ws.spectral_radiance_space_agenda)
"""
The local namespace of your python instance will now contain
the variable "cosmic_background". This is of type Agenda but is unchecked.
The assignment to "ws.iy_space_agenda" will cause the agenda to
be created, set, and checked on the current workspace. This checking might
fail if, for instance, a required input or output is missing.
It is possible to create a checked agenda that lives on the both the python
and on the pyarts workspace by specifying which workspace it should be set
on as a named argument to the agenda decorator:
"""
@pyarts.workspace.arts_agenda(ws=ws)
def spectral_radiance_space_agenda(ws):
ws.spectral_radianceUniformCosmicBackground()
ws.spectral_radiance_jacobianEmpty()
ws.Ignore(ws.ray_path_point)
print(spectral_radiance_space_agenda)
print(ws.spectral_radiance_space_agenda)
"""
Lastly, an advanced feature to skip typing ignores is to tell the property to
deal with this for you by fixing the agenda. Note that this might give you bad
results if the agenda is ever changed in a future update of ARTS as the method
will simply append all new input. Still, it is convenient:
"""
@pyarts.workspace.arts_agenda(ws=ws, fix=True)
def spectral_radiance_space_agenda(ws):
ws.spectral_radianceUniformCosmicBackground()
ws.spectral_radiance_jacobianEmpty()
print(spectral_radiance_space_agenda)
Atmospheric field from netcdf
This demonstrates how to set your atmospheric field using netcdf.
An atmospheric field is created using standard workspace method
flow. The atmospheric field is then gridded to a uniform grid
before being written to a netcdf file via the xarray.Dataset
format.
An helper method
import numpy as np
import pyarts3 as pyarts
# Download catalogs
pyarts.data.download()
# Use default atmosphere
ws = pyarts.Workspace()
ws.absorption_speciesSet(species=["O2", "CO2"])
ws.atmospheric_fieldRead(
toa=100e3, basename="planets/Earth/afgl/tropical/", missing_is_zero=1
)
# The atmospheric field must be uniformly gridded to be saved to a netcdf file
gridded_atm = ws.atmospheric_field.as_gridded(np.linspace(0, 100e3, 101), [0], [0])
# Save only O2 VMR, temperature and pressure to a netcdf file
gridded_atm.to_xarray(keys=["O2", "t", "p"]).to_netcdf("atmosphere.nc")
# Use helper method to read the netcdf file (if it is in any path seen by ARTS)
atmnc = pyarts.data.xarray_open_dataset("atmosphere.nc")
# Convert the xarray dataset to an atmospheric field
atm = pyarts.data.to_atmospheric_field(atmnc)