PyBats - SWMF & BATS-R-US Analysis Tools

PyBats! An open source Python-based interface for reading, manipulating, and visualizing BATS-R-US and SWMF output. For more information on the SWMF, please visit the Center for Space Environment Modeling.

See also the full API documentation.

PyBats Module

pybats

Introduction

At its most fundamental level, PyBats provides access to output files written by the Space Weather Modeling Framework and the codes contained within. The key task performed by PyBats is loading simulation data into a Spacepy data model object so that the user can move on to the important tasks of analyzing and visualizing the values. The secondary goal of PyBats is to make common tasks performed with these data as easy as possible. The result is that most SWMF output can be opened and visualized using only a few lines of code. Many complicated tasks, such as field line integration, is included as well.

Organization

Many output files in the SWMF share a common format. Objects to handle broad formats like these are found in the base module. The base module has classes to handle SWMF input files, as well.

The rest of the classes are organized by code, i.e. classes and functions specifically relevant to BATS-R-US can be found in spacepy.pybats.bats. Whenever a certain code included in the SWMF requires a independent class or a subclass from the PyBats base module, it will receive its own submodule.

Conventions and Prefixes

Nearly every class in PyBats inherits from spacepy.datamodel.SpaceData so it is important for users to understand how to employ and explore SpaceData objects. There are a few exceptions, so always pay close attention to the docstrings and examples. Legacy code that does not adhere to this pattern is slowly being brought up-to-date with each release.

Visualization methods have two prefixes: plot_ and add_. Whenever a method begins with plot_, a quick-look product will be created that is not highly- configurable. These methods are meant to yeild either simple diagnostic plots or static, often-used products. There are few methods that use this prefix. The prefix add_ is always followed by plot_type; it indicates a plotting method that is highly configurable and meant to be combined with other add_-like methods and matplotlib commands.

Common calculations, such as calculating Alfven wave speeds of MHD results, are strewn about PyBats’ classes. They are always given the method prefix calc_, i.e. calc_alfven. Methods called calc_all will search for all class methods with the calc_ prefix and call them.

Submodules

There are submodules for most models included within the SWMF. The classes and methods contained within are code-specific, yielding power and convenience at the cost of flexibility. A few of the submodules are helper modules- they are not code specific, but rather provide functionality not related to an SWMF-included code. See pybats API.

Top-Level Classes & Functions

Top-level PyBats classes handle common-format input and output from the SWMF and are very flexible. However, they do little beyond open files for the user.

There are several functions found in the top-level module. These are mostly convenience functions for customizing plots.

class IdlFile

The IdlFile class of pybats.

Introduction

An object class that reads/parses an IDL-formatted output file from the SWMF and places it into a spacepy.pybats.PbData object.

Usage: >>>data = spacepy.pybats.IdlFile(‘binary_file.out’)

See spacepy.pybats.PbData for information on how to explore data contained within the returned object.

This class serves as a parent class to SWMF component-specific derivative classes that do more preprocessing of the data before returning the object. Hence, using this class to read binary files is typically not the most efficient way to proceed. Look for a PyBats sub module that suits your specific needs, or use this base object to write your own.

Multi-Frame Files

Typically, Idl-formatted data has a single frame, or a single snapshot worth of data (a *.out file). However, it is possible to (externally) combine many of these files together such that a time series of data frames are contained within a single file (*.outs files). This class can read these files, but only one data frame can be made available at a time. This prevents very large memory requirements.

These files are opened and handled similarly to regular IDL-formatted files with some important differences. Upon instantiation, the user may select which data frame to open with the iframe kwarg. The default action is to open the first frame. The user may learn more about the number of frames within the file and their associated epoch/iteration information by examining the top level attrs (see below.) The user may switch to any arbitrary frame using the switch_frame(iframe) object method. This will load the relevant data from disk into the object, overwriting the previous contents.

If the user has created any new variables using the data from a certain data frame, those new values will not be updated automatically. An exception is for any self.calc_ type methods that are set to update automatically.

Top Level Attributes

Critical file information can be found via the top-level object attributes (e.g., accessing the dictionary self.attrs). All IdlFile objects and child classes begin with at least these attributes:

Attribute Name

Description

file

Path/Name of file represented by object

iter/time/runtime

Iteration/datetime/runtime of the current frame

iters/time/runtimes

Lists of all iterations/times of each data frame

range

The range of iterations/epochs covered in file

ndim

Number of spatial dimensions covered by the data

nframe

The total number of data frame within the file

iframe

The current frame loaded (zero-based)

format

The format of the file, either binary or ascii

header

The raw string header of the file

Notes

PyBats assumes little endian byte ordering because this is what most machines use. However, there is an autodetect feature such that, if PyBats doesn’t make sense of the first read (a record length entry, or RecLen), it will proceed using big endian ordering. If this doesn’t work, the error will manifest itself through the “struct” package as an “unpack requires a string of argument length ‘X’”.

Changed in version 0.5.0: Unstructured data are presented as in the files. When reading 3D magnetosphere files, this preserves the 3D block structure, as required for the BATSRUS interpolator in the Kamodo Heliophysics model readers package. Before 0.5.0, binary unstructured data were sorted in an attempt to put nearby positions close to each other in the data arrays. This sorting was nondeterministic and has been removed; see extract() and QTree for processing adjacent cells. (ASCII data were never sorted.)

class ImfInput

A class to read, write, manipulate, and visualize solar wind upstream input files for SWMF simulations. More about such files can be found in the SWMF/BATS-R-US documentation for the \#SOLARWINDFILE command.

Creating an ImfInput object is simple:

>>> from spacepy import pybats
>>> obj=pybats.ImfInput(filename='test.dat', load=True)

Upon instantiation, if filename is a valid file AND kwarg load is set to boolean True, the contents of filename are loaded into the object and no other work needs to be done.

If filename is False or load is False, a blank ImfInput file is created for the user to manipulate. The user can set the time array and the associated data values (see obj.attrs[‘var’] for a list) to any values desired and use the method obj.write() to dump the contents to an SWMF formatted input file. See the documentation for the write method for more details.

Like most pybats objects, you may interact with ImfInput objects as if they were specialized dictionaries. Access data like so:

>>> obj.keys()
['bx', 'by', 'bz', 'vx', 'vy', 'vz', 'n', 't']
>>> density=obj['n']

Adding new data entries is equally simple so long as you have the values and the name for the values:

>>> import numpy as np
>>> u = np.sqrt(obj['ux']**2 + obj['uy']**2 + obj['uz']**2)
>>> obj['u']=u

If new data entries are added as dmarray objects, the label and units attributes can be set to enhance plotting.

>>> from spacepy import datamodel
>>> u = np.sqrt(obj['ux']**2 + obj['uy']**2 + obj['uz']**2)
>>> obj['u']= datamodel.dmarray(u, {'units': '$km/s$', 'label': '|U|'})

Concerning Variable Naming & Order

By default, IMF files contain the following variables in this order:

Year, month, day, hour, minute, second, millisecond, bx, by, bz, vx, vy, vz, n, t

If the variable order changes, or if new state variables are included (e.g., species-specific densities for multi-ion simulations), the #VAR entry must be included in the solar wind file. While the SWMF documentation refers to density and temperature values as having names ‘dens’ or ‘temp’, only ‘n’, ‘t’, or MHD state variable names as defined in the BATS-R-US equation file are accepted.. In multi-ion simulations, ‘n’ is the total number density; all other densities must sum to ‘n’.

To illustrate, consider this example of converting a single fluid input file to a multi-fluid input file where density is split evenly across two ion species: a solar wind fluid and an ionosphere fluid that has minimal density upstream of the Earth. Each fluid has an explicit state variable name defined in the BATS-R-US equation module that configures the multi-fluid configuration.

>>> import numpy as np
>>> from spacepy import pybats, datamodel
>>> imf = pybats.ImfInput('tests/data/pybats_test/imf_single.dat')
>>> imf['IonoRho'] = datamodel.dmarray(np.zeros(imf['n'].shape) + 0.01,
... {'units': '$cm^{-3}$', 'label': '$\\rho_{Iono}$'})
>>> imf['SwRho'] = imf['n'] - imf['IonoRho']
>>> imf['SwRho'].attrs['label'] = '$\\rho_{Sw}$'
>>> imf.quicklook( ['bz', ['n', 'SwRho', 'IonoRho'], 'pram'])

Kwarg

Description

filename

Set the input/output file name.

load

Read file upon instantiation? Defaults to True

npoints

For empty data sets, sets number of points (default is 0)

Changed in version 0.5.0: Default variable names for temperature and density are now ‘t’ and ‘n’.

Bats Submodule

Bats2d

A child class of IdlFile tailored to 2D BATS-R-US output.

Calculations

New values can be added via the addition of new keys. For example, a user could add radial distance to an equatorial Bats2d object as follows:

>>> import numpy as np
>>> from spacepy.pybats import bats
>>> mhd = bats.Bats2d('tests/data/pybats_test/z=0_sine.out')
>>> mhd['rad'] = np.sqrt( mhd['x']**2 + mhd['y']**2 )

Note, however, that if the user switches the data frame in a .outs file to access data from a different epoch, these values will need to be updated.

An exception to this is built-in calc_* methods, which perform common MHD/fluid dynamic calculations (i.e., Alfven wave speed, vorticity, and more.) These values are updated when the data frame is switched (see the switch_frame method).

For example, to calculate number density and the fraction of the total density for each species in a multi-fluid simulation,

>>> mhd = bats.Bats2d('tests/data/pybats_test/cut_multispecies.out')
>>> mhd.calc_ndens()

In an interactive session, users can tab-complete to explore the possible built-in calculation methods.

Plotting

While users can employ Matplotlib to plot values, a set of built-in methods are available to expedite plotting. These are the add_<plot type> methods. These methods always have the following keyword arguments that allow users to optionally build more complicated plots: target and loc. The target kwarg tells the plotting method where to place the plot and can either be a Matplotlib figure or axes object. If it’s an axes object, loc sets the subplot location using the typical matplotlib syntax (e.g., loc=121). The default behavior is to create a new figure and axes object.

This approach allows a user to over-plot contours, field lines, and other plot artists as well as combine different subplots onto a single figure. Continuing with our example above, let’s plot the grid layout for our file as well as equatorial pressure and flow streamlines:

>>> import matplotlib.pyplot as plt
>>> fig = plt.Figure(figsize=(8,6))
>>> mhd.add_grid_plot(target=fig, loc=121)
>>> mhd.add_contour('x','y','p', target=fig, loc=122)
>>> mhd.add_stream_scatter('ux', 'uy', target=fig, loc=122)

Useful plotting methods include the following:

Plot Method

Description

add_grid_plot

Create a quick-look diagram of the grid layout

add_contour

Create a contour plot of a given variable

add_pcolor

Add a p-color (no-interpolation contour) plot

add_stream_scatter

Scatter stream traces (any vector field)

add_b_magsphere

Add magnetic field lines for X-Z plane cuts

add_planet

Add a simple black/white planet at the origin

add_body

Add an inner boundary at the origin

Extracting and Stream Tracing

Extracting values via interpolation to arbitrary points and creating stream traces through any vector field (e.g., velocity or magnetic field) are aided via the use of the following object methods:

Method

Description

extract

Interpolate to arbitrary points and extract values

get_stream

Integrate stream lines through vector fields

Be sure to read the docstring information of IdlFile to see how to handle multi-frame files (.outs) and for a list of critical attributes.

Changed in version 0.5.0: Unstructured data are now presented as in the files. See IdlFile for details.