boututils package

Module contents

Generic routines, useful for all data

Submodules

boututils.analyse_equil_2 module

boututils.anim module

boututils.ask module

Ask a yes/no question and return the answer.

boututils.ask.query_yes_no(question, default='yes')

Ask a yes/no question via input() and return their answer.

Answers are case-insensitive.

Probably originally from http://code.activestate.com/recipes/577058/ via https://stackoverflow.com/a/3041990/2043465

Parameters:
  • question (str) – Question to be presented to the user
  • default ({“yes”, “no”, None}) – The presumed answer if the user just hits <Enter>. It must be “yes” (the default), “no” or None (meaning an answer is required of the user).
Returns:

True if the answer was “yes” or “y”, False if “no” or “n”

Return type:

bool

boututils.boutarray module

Wrapper for ndarray with extra attributes for BOUT++ fields.

class boututils.boutarray.BoutArray

Bases: numpy.ndarray

Wrapper for ndarray with extra attributes for BOUT++ fields.

Parameters:
  • input_array (array_like) – Data to convert to BoutArray

  • attributes (dict) – Dictionary of extra attributes for BOUT++ fields

    Notably, these attributes should contain bout_type. Possible values are:

    • scalar
    • Field2D
    • Field3D

    If the variable is an evolving variable (i.e. has a time dimension), then it is appended with a “_t”

boututils.boutgrid module

boututils.boutwarnings module

Wrappers for warnings functions.

Allows raising warnings that are always printed by default.

exception boututils.boutwarnings.AlwaysWarning(*args, **kwargs)
boututils.boutwarnings.alwayswarn(message)
boututils.boutwarnings.defaultwarn(message)

boututils.calculus module

Derivatives and integrals of periodic and non-periodic functions

B.Dudson, University of York, Nov 2009

boututils.calculus.deriv(*args, **kwargs)

Take derivative of 1D array

result = deriv(y) result = deriv(x, y)

keywords

periodic = False Domain is periodic

boututils.calculus.deriv2D(data, axis=-1, dx=1.0, noise_suppression=True)

Takes 1D or 2D Derivative of 2D array using convolution

result = deriv2D(data) result = deriv2D(data, dx)

output is 2D (if only one axis specified) output is 3D if no axis specified [nx,ny,2] with the third dimension being [dfdx, dfdy]

keywords: axis = 0/1 If no axis specified 2D derivative will be returned dx = 1.0 axis spacing, must be 2D if 2D deriv is taken - default is [1.0,1.0] noise_suppression = True noise suppressing coefficients used to take derivative - default = True

boututils.calculus.integrate(var, periodic=False)

Integrate a 1D array

Return array is the same size as the input

boututils.calculus.simpson_integrate(data, dx, dy, kernel=0.0, weight=1.0)

Integrates 2D data to one value using the simpson method and matrix convolution

result = simpson_integrate(data,dx,dy)

keywords:

kernel - can be supplied if the simpson matrix is calculated ahead of time
  • if not supplied, is calculated within this function
  • if you need to integrate the same shape data over and over, calculated
    it ahead of time using:
    kernel = simpson_matrix(Nx,Ny,dx,dy)
weight - can be used to scale data if single number
  • can be used to mask data if weight is array (same size as data)
boututils.calculus.simpson_matrix(Nx, Ny, dx, dy)

Creates a 2D matrix of coefficients for the simpson_integrate function

Call ahead of time if you need to perform integration of the same size data with the
same dx and dy

Otherwise, simpson_integrate will automatically call this

boututils.closest_line module

boututils.closest_line.closest_line(n, x, y, ri, zi, mind=None)

boututils.contour module

Contour calculation routines

http://members.bellatlantic.net/~vze2vrva/thesis.html

boututils.contour.contour(f, level)

Return a list of contours matching the given level

boututils.contour.find_opoints(var2d)

Find O-points in psi i.e. local minima/maxima

boututils.contour.find_xpoints(var2d)

Find X-points in psi i.e. inflection points

boututils.crosslines module

boututils.crosslines.find_inter(contour1, contour2)
boututils.crosslines.linelineintersect(a, b, atol=1e-08)

Find all intersection points of two lines defined by series of x,y pairs

Intersection points are unordered Colinear lines that overlap intersect at any end points that fall within the overlap

Parameters:a, b (ndarray) – 2 column ndarray of x,y values defining a two dimensional line. 1st column is x values, 2nd column is x values.

Notes

An example of 3 segment line is: a = numpy.array([[0,0],[5.0,3.0],[4.0,1]]) Function faster when there are no overlapping line segments

add some lines for preventing zero-division

boututils.crosslines.unique(a, atol=1e-08)

Find unique rows in 2d array

Parameters:
  • a (2d ndarray, float) – array to find unique rows in
  • atol (float, optional) – tolerance to check uniqueness
Returns:

out – array of unique values

Return type:

2d ndarray, float

Notes

Adapted to include tolerance from code at http://stackoverflow.com/questions/8560440/removing-duplicate-columns-and-rows-from-a-numpy-2d-array#answer-8564438

boututils.datafile module

File I/O class

A wrapper around various NetCDF libraries and h5py, used by BOUT++ routines. Creates a consistent interface across machines

Supported libraries:

  • h5py (for HDF5 files)
  • netCDF4 (preferred NetCDF library)

Note

NetCDF and HDF5 include unlimited dimensions, but this library is just for very simple I/O operations. Educated guesses are made for the dimensions.

class boututils.datafile.DataFile(filename=None, write=False, create=False, format='NETCDF3_64BIT', **kwargs)

File I/O class

A wrapper around various NetCDF libraries and h5py, used by BOUT++ routines. Creates a consistent interface across machines

Parameters:
  • filename (str, optional) – Name of file to open. If no filename supplied, you will need to call open and supply filename there
  • write (bool, optional) – If True, open the file in read-write mode (existing files will be appended to). Default is read-only mode
  • create (bool, optional) – If True, open the file in write mode (existing files will be truncated). Default is read-only mode
  • format (str, optional) – Name of a filetype to use (e.g. NETCDF3_CLASSIC, NETCDF3_64BIT, NETCDF4, HDF5)
attributes(varname)

Return a dictionary of attributes

Parameters:varname (str) – The name of the variable
Returns:The attribute names and their values
Return type:dict
bout_type(varname)

Return the name of the BOUT++ type of a variable

Possible values are:

  • scalar
  • Field2D
  • Field3D

If the variable is an evolving variable (i.e. has a time dimension), then it is appended with a “_t”

Parameters:varname (str) – The name of the variable
Returns:The name of the BOUT++ type
Return type:str
close()

Close a file and flush data to disk

dimensions(varname)

Return the names of all the dimensions of a variable

Parameters:varname (str) – The name of the variable
Returns:The names of the variable’s dimensions
Return type:tuple of str
impl = None
keys()

A synonym for list

list()

List all variables in the file

Returns:A list containing all the names of the variables
Return type:list of str
ndims(varname)

Return the number of dimensions for a variable

Parameters:varname (str) – The name of the variable
Returns:The number of dimensions
Return type:int
open(filename, write=False, create=False, format='NETCDF3_CLASSIC')

Open the file

Parameters:
  • filename (str, optional) – Name of file to open
  • write (bool, optional) – If True, open the file in read-write mode (existing files will be appended to). Default is read-only mode
  • create (bool, optional) – If True, open the file in write mode (existing files will be truncated). Default is read-only mode
  • format (str, optional) – Name of a filetype to use (e.g. NETCDF3_CLASSIC, NETCDF4, HDF5)
read(name, ranges=None, asBoutArray=True)

Read a variable from the file

Parameters:
  • name (str) – Name of the variable to read
  • ranges (list of slice objects, optional) – Slices of variable to read, can also be converted from lists or tuples of (start, stop, stride). The number of elements in ranges should be equal to the number of dimensions of the variable you wish to read. See size for how to get the dimensions
  • asBoutArray (bool, optional) – If True, return the variable as a BoutArray (the default)
Returns:

The variable from the file (BoutArray if asBoutArray is True)

Return type:

ndarray or BoutArray

size(varname)

Return the size of each dimension of a variable

Parameters:varname (str) – The name of the variable
Returns:The size of each dimension
Return type:tuple of int
sync()

Write pending changes to disk.

write(name, data, info=False)

Write a variable to file

If the variable is not a BoutArray with the bout_type attribute, a guess will be made for the dimensions

Parameters:
  • name (str) – Name of the variable to use in the file
  • data (BoutArray or ndarray) – An array containing the variable data
  • info (bool, optional) – If True, print information about what is being written to file
Returns:

Return type:

None

class boututils.datafile.DataFile_HDF5(filename=None, write=False, create=False, format=None)
attributes(varname)

Return a dictionary of attributes

Parameters:varname (str) – The name of the variable
Returns:The attribute names and their values
Return type:dict
close()

Close a file and flush data to disk

dimensions(varname)

Return the names of all the dimensions of a variable

Parameters:varname (str) – The name of the variable
Returns:The names of the variable’s dimensions
Return type:tuple of str
handle = None
keys()

A synonym for list

list()

List all variables in the file

Returns:A list containing all the names of the variables
Return type:list of str
ndims(varname)

Return the number of dimensions for a variable

Parameters:varname (str) – The name of the variable
Returns:The number of dimensions
Return type:int
open(filename, write=False, create=False, format=None)

Open the file

Parameters:
  • filename (str, optional) – Name of file to open
  • write (bool, optional) – If True, open the file in read-write mode (existing files will be appended to). Default is read-only mode
  • create (bool, optional) – If True, open the file in write mode (existing files will be truncated). Default is read-only mode
  • format (str, optional) – Name of a filetype to use (e.g. NETCDF3_CLASSIC, NETCDF4, HDF5)
read(name, ranges=None, asBoutArray=True)

Read a variable from the file

Parameters:
  • name (str) – Name of the variable to read
  • ranges (list of slice objects, optional) – Slices of variable to read, can also be converted from lists or tuples of (start, stop, stride). The number of elements in ranges should be equal to the number of dimensions of the variable you wish to read. See size for how to get the dimensions
  • asBoutArray (bool, optional) – If True, return the variable as a BoutArray (the default)
Returns:

The variable from the file (BoutArray if asBoutArray is True)

Return type:

ndarray or BoutArray

size(varname)

Return the size of each dimension of a variable

Parameters:varname (str) – The name of the variable
Returns:The size of each dimension
Return type:tuple of int
sync()

Write pending changes to disk.

write(name, data, info=False)

Write a variable to file

If the variable is not a BoutArray with the bout_type attribute, a guess will be made for the dimensions

Parameters:
  • name (str) – Name of the variable to use in the file
  • data (BoutArray or ndarray) – An array containing the variable data
  • info (bool, optional) – If True, print information about what is being written to file
Returns:

Return type:

None

class boututils.datafile.DataFile_netCDF(filename=None, write=False, create=False, format='NETCDF3_CLASSIC', **kwargs)
attributes(varname)

Return a dictionary of attributes

Parameters:varname (str) – The name of the variable
Returns:The attribute names and their values
Return type:dict
close()

Close a file and flush data to disk

dimensions(varname)

Return the names of all the dimensions of a variable

Parameters:varname (str) – The name of the variable
Returns:The names of the variable’s dimensions
Return type:tuple of str
handle = None
keys()

A synonym for list

list()

List all variables in the file

Returns:A list containing all the names of the variables
Return type:list of str
ndims(varname)

Return the number of dimensions for a variable

Parameters:varname (str) – The name of the variable
Returns:The number of dimensions
Return type:int
open(filename, write=False, create=False, format='NETCDF3_CLASSIC')

Open the file

Parameters:
  • filename (str, optional) – Name of file to open
  • write (bool, optional) – If True, open the file in read-write mode (existing files will be appended to). Default is read-only mode
  • create (bool, optional) – If True, open the file in write mode (existing files will be truncated). Default is read-only mode
  • format (str, optional) – Name of a filetype to use (e.g. NETCDF3_CLASSIC, NETCDF4, HDF5)
read(name, ranges=None, asBoutArray=True)

Read a variable from the file.

size(varname)

Return the size of each dimension of a variable

Parameters:varname (str) – The name of the variable
Returns:The size of each dimension
Return type:tuple of int
sync()

Write pending changes to disk.

write(name, data, info=False)

Write a variable to file

If the variable is not a BoutArray with the bout_type attribute, a guess will be made for the dimensions

Parameters:
  • name (str) – Name of the variable to use in the file
  • data (BoutArray or ndarray) – An array containing the variable data
  • info (bool, optional) – If True, print information about what is being written to file
Returns:

Return type:

None

boututils.efit_analyzer module

boututils.fft_deriv module

boututils.fft_deriv.fft_deriv(var)

boututils.fft_integrate module

boututils.fft_integrate.fft_integrate(y, loop=None)
boututils.fft_integrate.test_integrate()

boututils.file_import module

Import an entire BOUT++ DataFile into memory

boututils.file_import.file_import(name)

Read all variables from file into a dictionary

Parameters:name (str) – Name of file to read
Returns:Dictionary containing all the variables in the file
Return type:dict

boututils.geqdsk module

class boututils.geqdsk.Geqdsk
get(varname)
getAll()
getAllVars()
getDescriptor(varname)
openFile(filename)

open geqdsk file and parse its content

boututils.geqdsk.main()

boututils.idl_tabulate module

boututils.idl_tabulate.idl_tabulate(x, f, p=5)

boututils.int_func module

boututils.int_func.int_func(xin, fin=None, simple=None)

boututils.linear_regression module

boututils.linear_regression.linear_regression(x, y)

Simple linear regression of two variables

y = a + bx

a, b = linear_regression(x, y)

boututils.local_min_max module

boututils.local_min_max.detect_local_maxima(arr)

Takes an array and detects the peaks using the local maximum filter. Returns a boolean mask of the troughs (i.e. 1 when the pixel’s value is the neighborhood maximum, 0 otherwise)

boututils.local_min_max.detect_local_minima(arr)

Takes an array and detects the troughs using the local maximum filter. Returns a boolean mask of the troughs (i.e. 1 when the pixel’s value is the neighborhood maximum, 0 otherwise)

boututils.mode_structure module

boututils.mode_structure.mode_structure(var_in, grid_in, period=1, zangle=0.0, n=None, addq=None, output=None, xq=None, xpsi=None, slow=None, subset=None, filter=None, famp=None, quiet=None, ergos=None, ftitle=None, xrange=None, yrange=None, rational=None, pmodes=None, _extra=None)
boututils.mode_structure.zinterp(v, zind)

boututils.moment_xyzt module

boututils.moment_xyzt.RMSvalue(vec1d)
boututils.moment_xyzt.moment_xyzt(sig_xyzt, *args)

boututils.options module

Module to allow BOUT.inp files to be read into python and manipulated with ease.

Nick Walkden, June 2015 nick.walkden@ccfe.ac.uk

class boututils.options.BOUTOptions(inp_path=None)

Class to store and interact with options from BOUT++

Parameters:inp_path (str, optional) – Path to BOUT++ options file

Examples

Instantiate with

>>> myOpts = BOUTOptions()
>>> myOpts.read_inp('path/to/input/file')

or

>>> myOpts = BOUTOptions('path/to/input/file')

To get a list of sections use

>>> section_list = myOpts.list_sections
>>> # Also print to screen:
>>> section_list = myOpts.list_sections(verbose=True)

Each section of the input is stored as a dictionary attribute so that, if you want all the settings in the section [ddx]:

>> ddx_opt_dict = myOpts.ddx

and access individual settings by

>>> ddx_setting = myOpts.ddx['first']

Any settings in BOUT.inp without a section are stored in

>>> root_dict = myOpts.root
add_section(section)

Add a section to the options

Parameters:section (str) – The name of a new section
list_sections(verbose=False)

Return all the sections in the options

Parameters:verbose (bool, optional) – If True, print sections to screen
read_inp(inp_path='')

Read a BOUT++ input file

Parameters:inp_path (str, optional) – Path to the input file (default: current directory)
remove_section(section)

Remove a section from the options

Parameters:section (str) – The name of a section to remove

boututils.plotdata module

boututils.plotdata.plotdata(data, x=None, y=None, title=None, xtitle=None, ytitle=None, output=None, range=None, fill=True, mono=False, colorbar=True, xerr=None, yerr=None)

Plot 1D or 2D data, with a variety of options.

boututils.plotdata.test()

Test the plotdata routine.

boututils.plotpolslice module

boututils.radial_grid module

boututils.radial_grid.radial_grid(n, pin, pout, include_in, include_out, seps, sep_factor, in_dp=None, out_dp=None)

boututils.read_geqdsk module

boututils.run_wrapper module

Collection of functions which can be used to make a BOUT++ run

boututils.run_wrapper.determineNumberOfCPUs()

Number of virtual or physical CPUs on this system

i.e. user/real as output by time(1) when called with an optimally scaling userspace-only program

Taken from a post on stackoverflow: http://stackoverflow.com/questions/1006289/how-to-find-out-the-number-of-cpus-in-python

Returns:The number of CPUs
Return type:int
boututils.run_wrapper.getmpirun(default='mpirun -np')
Return environment variable named MPIRUN, if it exists else return
a default mpirun command
Parameters:default (str, optional) – An mpirun command to return if MPIRUN is not set in the environment
boututils.run_wrapper.launch(command, runcmd=None, nproc=None, mthread=None, output=None, pipe=False, verbose=False)

Launch parallel MPI jobs

>>> status = launch(command, nproc, output=None)
Parameters:
  • command (str) – The command to run
  • runcmd (str, optional) – Command for running parallel job; defaults to what getmpirun() returns”
  • nproc (int, optional) – Number of processors (default: all available processors)
  • mthread (int, optional) – Number of omp threads (default: the value of the OMP_NUM_THREADS environment variable
  • output (str, optional) – Name of file to save output to
  • pipe (bool, optional) – If True, return the output of the command
  • verbose (bool, optional) – Print the full command to be run before running it
Returns:

tuple – The return code, and either command output if pipe=True else None

Return type:

(int, str)

boututils.run_wrapper.launch_safe(command, *args, **kwargs)

‘Safe’ version of launch.

Raises an RuntimeError exception if the command is not successful

Parameters:
  • command (str) – The command to run
  • *args, **kwargs – Optional arguments passed to shell
boututils.run_wrapper.shell(command, pipe=False)

Run a shell command

Parameters:
  • command (list of str) – The command to run, split into (shell) words
  • pipe (bool, optional) – Grab the output as text, else just run the command in the background
Returns:

tuple – The return code, and either command output if pipe=True else None

Return type:

(int, str)

boututils.run_wrapper.shell_safe(command, *args, **kwargs)

‘Safe’ version of shell.

Raises a RuntimeError exception if the command is not successful

Parameters:
  • command (str) – The command to run
  • *args, **kwargs – Optional arguments passed to shell

boututils.showdata module

Visualisation and animation routines

Written by Luke Easy le590@york.ac.uk Last Updated 19/3/2015 Additional functionality by George Breyiannis 26/12/2014

boututils.showdata.showdata(vars, titles=[], legendlabels=[], surf=[], polar=[], tslice=0, t_array=None, movie=0, fps=28, dpi=200, intv=1, Ncolors=25, x=[], y=[], global_colors=False, symmetric_colors=False, hold_aspect=False, cmap=None, clear_between_frames=None, return_animation=False, window_title='')

A Function to animate time dependent data from BOUT++

To animate multiple variables on different axes:

>>> showdata([var1, var2, var3])

To animate more than one line on a single axes:

>>> showdata([[var1, var2, var3]])

The default graph types are: 2D (time + 1 spatial dimension) arrays = animated line plot 3D (time + 2 spatial dimensions) arrays = animated contour plot.

To use surface or polar plots:

>>> showdata(var, surf=1)
>>> showdata(var, polar=1)

Can plot different graph types on different axes. Default graph types will be used depending on the dimensions of the input arrays. To specify polar/surface plots on different axes:

>>> showdata([var1, var2], surf=[1, 0], polar=[0, 1])

Movies require FFmpeg (for .mp4) and/or ImageMagick (for .gif) to be installed. The ‘movie’ option can be set to 1 (which will produce an mp4 called ‘animation.mp4’), to a name with no extension (which will produce an mp4 called ‘<name>.mp4’)

The tslice variable is used to control the time value that is printed on each frame of the animation. If the input data matches the time values found within BOUT++’s dmp data files, then these time values will be used. Otherwise, an integer counter is used.

The cmap variable (if specified) will set the colormap used in the plot cmap must be a matplotlib colormap instance, or the name of a registered matplotlib colormap

During animation click once to stop in the current frame. Click again to continue.

Parameters:
  • vars (array_like or list of array_like) – Variable or list of variables to plot
  • titles (str or list of str, optional) – Title or list of titles for each axis
  • legendlabels (str or list of str, optional) – Legend or list of legends for each variable
  • surf (list of int) – Which axes to plot as a surface plot
  • polar (list of int) – Which axes to plot as a polar plot
  • tslice (list of int) – Use these time values from a dump file (see above)
  • t_array (array) – Pass in t_array using this argument to use the simulation time in plot titles. Otherwise, just use the t-index.
  • movie (int) – If 1, save the animation to file
  • fps (int) – Number of frames per second to use when saving animation
  • dpi (int) – Dots per inch to use when saving animation
  • intv (int) – ???
  • Ncolors (int) – Number of levels in contour plots
  • x, y (array_like, list of array_like) – X, Y coordinates
  • global_colors (bool) – If “vars” is a list the colorlevels are determined from the maximum of the maxima and and the minimum of the minima in all fields in vars
  • symmetric_colors (bool) – Colour levels are symmetric
  • hold_aspect (bool) – Use equal aspect ratio in plots
  • cmap (colormap) – A matplotlib colormap instance to use
  • clear_between_frames (bool, optional) –
    • Default (None) - all plots except line plots will clear between frames
    • True - all plots will clear between frames
    • False - no plots will clear between frames
  • return_animation (bool) – Return the matplotlib animation instance
  • window_title (str) – Give a title for the animation window

boututils.spectrogram module

Creates spectrograms using the Gabor transform to maintain time and frequency resolution

written by: Jarrod Leddy updated: 23/06/2016

boututils.spectrogram.spectrogram(data, dx, sigma, clip=1.0, optimise_clipping=True, nskip=1.0)

Creates spectrograms using the Gabor transform to maintain time and frequency resolution

Note

Very early and very late times will have some issues due to the method - truncate them after taking the spectrogram if they are below your required standards

Note

If you are seeing issues at the top or bottom of the frequency range, you need a longer time series

written by: Jarrod Leddy updated: 23/06/2016

Parameters:
  • data (array_like) – The time series you want spectrogrammed

  • dt (float) – Time resolution

  • sigma (float) – Used in the Gabor transform, will balance time and frequency resolution suggested value is 1.0, but may need to be adjusted manually until result is as desired:

    • If bands are too tall raise sigma
    • If bands are too wide, lower sigma
  • clip (float, optional) – Makes the spectrogram run faster, but decreases frequency resolution. clip is by what factor the time spectrum should be clipped by –> N_new = N / clip

  • optimise_clip (bool) – If true (default) will change the data length to be 2^N (rounded down from your inputed clip value) to make FFT’s fast

  • nskip (float) – Scales final time axis, skipping points over which to centre the gaussian window for the FFTs

Returns:

tuple – A tuple containing the spectrogram, frequency and time

Return type:

(array_like, array_like, array_like)

boututils.spectrogram.test_spectrogram(n, d, s)

Function used to test the performance of spectrogram with various values of sigma

Parameters:
  • n (int) – Number of points
  • d (float) – Grid spacing
  • s (float) – Initial sigma

boututils.surface_average module

Average over a surface

boututils.surface_average.surface_average(var, g, area=None)

Average a variable over a surface

Parameters:
  • var (array_like) – 3-D or 4D variable to integrate (either [x,y,z] or [t,x,y,z])
  • g (dict) – A dictionary of various grid quantities
  • area (bool) – Average by flux-surface area = (B/Bp)*dl * R*dz
Returns:

Surface average of variable

Return type:

float

boututils.volume_integral module

Integrate over a volume

boututils.volume_integral.volume_integral(var, g, xr=False)

Integrate a variable over a volume

Parameters:
  • var (array_like) – Variable to integrate
  • g (dict) – A dictionary of various grid quantities
  • xr ((int, int), optional) – Range of x indices (default: all of x)
Returns:

Volumne integral of variable

Return type:

float

boututils.watch module

Routines for watching files for changes

boututils.watch.watch(files, timeout=None, poll=2)

Watch a given file or collection of files until one changes. Uses polling.

Parameters:
  • files (str or list of str) – Name of one or more files to watch
  • timeout (int, optional) – Timeout in seconds (default is no timeout)
  • poll (int, optional) – Polling interval in seconds (default: 2)
Returns:

The name of the first changed file, or None if timed out before any changes

Return type:

str

Examples

To watch one file, timing out after 60 seconds:

>>> watch('file1', timeout=60)

To watch 2 files, never timing out:

>>> watch(['file1', 'file2'])

Author: Ben Dudson <benjamin.dudson@york.ac.uk>

Module contents

Generic routines, useful for all data