ECLI utility functions

ecli_util – Utility functions for ECLI developers

ecli_util.check – Simple string conversion checks

ecli_util.check.check_bool(value)

Ensures a proper boolean value (even from a string). Raises UsageError on failure

ecli_util.check.check_float(value)

Ensures a proper floating-point value. Raises UsageError if not

ecli_util.check.check_int(value)

Ensures a proper integer value (from a string). Raises UsageError if not

ecli_util.conditional_monitor – PV monitor utility

class ecli_util.conditional_monitor.ConditionalMonitor(pv, desired_value=None, desired_epsilon=1e-05, stop_condition_pv=None, stop_pv_value=None, wait=False, stop_index=0, timeout=None, use_type=None, stop_event=None, connection_timeout=2.0, pv_timeout=1.0, poll_rate=0.01, update_cb=None, print_updates=False, print_file=<open file '<stdout>', mode 'w' at 0x40294078>)
Monitors a PV until one of several conditions occur:
  1. Ctrl-C is hit

  2. desired_value is reached (if numeric, within desired_epsilon)

  3. The PV stop_condition_pv changes
    1. If stop_pv_value is set, then it waits for this condition
    2. Otherwise, when the pv changes, the monitor will stop
  4. The timeout value is reached

  5. The timeout event is triggered (a threading.Event instance)

  6. The update callback function returns False

Stop condition value can be a tuple/list, such that the full set of conditions should be followed in order.

aborted

Was the monitor cancelled?

desired_epsilon

The factor by which desired_value can differ from the actual value

desired_value

The desired value to reach, after which the monitor can stop

pv

The main PV

stop()

Stop monitoring and waiting.

stop_pv

The PV to monitor for a stop condition

stop_updated(pvname=None, value=None, char_value=None, **kwargs)

Stop PV value updated callback

value_updated(timestamp=None, pvname=None, value=None, char_value=None, **kwargs)

PV value updated callback

wait()

Waits for the conditions in ConditionalMonitor.__doc__

Raises TimeoutError

ecli_util.decorators – ECLI function decorators

ecli_util.decorators.ECLIExport(fcn)

Simple decorator to indicate the function should be exported to the user namespace

class ecli_util.decorators.ECLIExported

ECLI exported function

class ecli_util.decorators.ShowElapsed(display_toggle=None, format_='n Elapsed: %.3g', file_=<open file '<stdout>', mode 'w' at 0x40294078>)

Decorator for (optionally) showing elapsed times of commands.

ecli_util.decorators.evaluate_arguments(fcn)

(decorator) Use the user namespace in IPython to evaluate each argument

Parameters:fcn – The function to decorate
ecli_util.decorators.expand_aliases(fcn=None, no_expansion=[])

(decorator) Expand aliases in a command

Parameters:
  • fcn – The function to decorate
  • no_expansion – A list of argument indices to not expand
ecli_util.decorators.wrap_command(fcn)

(decorator) Allows exported functions to be called in a simple fashion:

For example,
monitor pv
instead of
monitor(‘pv’)
Parameters:fcn – The function to decorate

ecli_util.epics_device – ECLI pyEpics device utilities

ecli_util.epics_device.get_record_from_device(s)

If the device is an epics.Device instance, return just the PV.

Returns:a PV, or raises UsageError if invalid
ecli_util.epics_device.get_records_from_devices(device_list)

Like get_record_from_device but accepts a list of devices/records.

ecli_util.epics_util – ECLI epics utilities

ecli_util.epics_util.get_motor_limits(motor_rec)

Get the user limits, given a motor record

ecli_util.epics_util.get_motor_rbv_pv(motor)

Get the associated (user) readback-value PV from a given motor record.

ecli_util.epics_util.get_record_type(pv)

Get the record type

ecli_util.epics_util.is_motor_record(rec)

Is rec an actual motor record?

ecli_util.epics_util.is_scan_record(rec)

Is rec an actual sscan record?

ecli_util.errors – ECLI errors and exceptions

ecli_util.magic_args – IPython magic_args helpers

class ecli_util.magic_args.AliasedPV

Used for magic_arguments (argparse), it allows for automatic expansion of PV aliases

ecli_util.magic_args.argument_count_range(nmin=None, nmax=None)

For magic arguments, sets a minimum number/maximum number of arguments. Partly from http://stackoverflow.com/questions/4194948

ecli_util.magic_args.argument_or_flag

alias of RequiredLength

ecli_util.magic_args.export_class_magic(ipython, instance)

Functions of a class instance that are decorated with specific decorators will be exported to the user in IPython.

Parameters:
  • ipython – the IPython shell instance
  • instance – the class instance to look check via introspection
ecli_util.magic_args.export_magic_by_decorator(ipython, obj, magic_arguments=True, modify_name=None, strip_underscores=True, wrap_fcn=None)

Functions that are decorated with specific decorators will be exported to the user in IPython.

Parameters:
  • ipython – the IPython shell instance
  • obj – the namespace (e.g., globals()) to check for functions, or alternatively, an instance of a class
  • magic_arguments (bool) – export functions decorated with magic_arguments
  • strip_underscores – remove underscores from beginning of function name. This is useful if exported func() and magic %func both exist.
  • modify_name – callback optionally allowing to change the exported name. new_name = modify_name(old_name, obj) strip_underscores is ignored if this is used.
  • wrap_fcn – optionally wrap the function prior to exporting it
ecli_util.magic_args.export_magic_by_prefix(ipython, ns, prefix='ipy_', strip_prefix=True)

Functions/classes/etc that start with prefix will be exported (i.e., accessible in ipython) to the user namespace

Parameters:
  • ipython – the IPython shell instance
  • ns – the namespace (e.g., globals()) to check for functions
  • prefix – the prefix to check for
  • strip_prefix – strip off the prefix before exporting

ecli_util.misc – miscellaneous utilities

class ecli_util.misc.OutputStreamHandler(write_fcn=None, flush_fcn=None)

Redirects an output stream to a callback functions

ecli_util.misc.clear_line()

Clear the current line of text on the terminal.

ecli_util.misc.edit_file(fn, editor=None)

Edit a file with the system’s default editor.

Parameters:
  • fn – the file to edit
  • editor – optionally specify the editor to use
ecli_util.misc.fix_label(label)

No spaces for SPS ‘axistitles’ No commas for SPS ‘plotlist’

ecli_util.misc.get_column_formatting_string(lines, fixed_width_format='%%-%ds', full_width_format='%s', delim=' ')

Assuming a sequence of string lists: calculate the maximum width of each column, and generate a format string so all lines can be printed neatly in a tabular format.

Output example for 3 columns, with maximum widths of 5, 2, and 3:
%-5s %-2s %3s
ecli_util.misc.get_column_widths(lines, maximum_width=100)
Assuming lines has the format:
[ [item, item, ...], [item, item, ...], ... ]

Where each line has the same number of items, and each item supports a conversion to string, calculate the maximum width of each column, and return it as a list.

ecli_util.misc.load_csv_header(fname, main_col='field', delimiter='\t')

Expects a (tab) delimited file with the first row being a header (column names) Lines starting with # are ignored (after the first row) Raises ValueError if main column not present

For example:

Field   name1   name2
field_1 value1  value2
...

Returns a dictionary:

{ 'field_1' : { 'name1' : 'value1', 'name2' : 'value2', ... }, ... }
ecli_util.misc.print_sameline(*args, **kwargs)

Print text on the same line (same arguments as the Python print function)

ecli_util.misc.print_table(rows, min_col_width=5, format_str=u'{:>%d}', f=<open file '<stdout>', mode 'w' at 0x40294078>, delimiter=u' ', first_column_format=None, remove_empty=True)

Not to be confused with the SimpleTable class, this prints out a table stored as a list of lists:

[['row1, 1', 'row1, 2', '...'], ['row2', ...'], ...]
Parameters:
  • rows – the rows
  • min_col_width – minimum column width (spaces)
  • format_str – the format string to use with str.format() defaults to right-aligned columns
  • f – the file/stream to output to (requires write method)
  • delimeter – the delimeter to print between columns
  • first_column_format – the first column can optionally have a different format
  • remove_empty – remove empty columns first
Returns:

the printed rows

ecli_util.misc.print_traceback(ex=None, f=<open file '<stderr>', mode 'w' at 0x402940d0>)

Dump a text traceback from the last exception to the file specified

Parameters:
  • ex – the exception to print
  • f – the file to dump to
ecli_util.misc.remove_columns(table, remove_columns, in_place=False)

From a list of rows, remove columns by index

Parameters:
  • rows – the rows
  • remove_columns – the column indices to remove
  • in_place – if in-place, the list will be modified
ecli_util.misc.remove_empty_columns(rows, in_place=False)

From a list of rows, remove empty columns.

Parameters:
  • rows – the rows
  • in_place – if in-place, the list will be modified

ecli_util.record_info – EPICS record information

class ecli_util.record_info.RecordFields(rtyp=None, fn=None)

Inefficiently manages record field information, loaded from text files located in records/*.txt (relative to this file)

find(text, columns=None, case_sensitive=False)

Find “text” in any column or field name

generate_dict(columns, fill_value=None)

From the detailed information in the database, return a simplified one containing only the main keys and the specified field(s).

If one field is specified, the result is:
{ ‘field’ : ‘value’ }
Otherwise, it’s a list in the same order as ‘columns’:
{ ‘field’ : [‘value1’, ‘value2’] }
ecli_util.record_info.get_record_fields(rtyp)

Get the RecordFields instance associated with the specific record type (rtyp) – e.g., ‘motor’ or ‘ai’

Note

As the RecordFields instances are cached, users should use this function instead of instantiating their own.

ecli_util.simple_table

class ecli_util.simple_table.SimpleTable(headers=[], empty='')

A simple, inefficient representation of a table, where data is stored by column. Column header text must be unique.

add_column(header, index=None, fill=None)

Add a column with a header before index in the table, filling its contents with fill.

Parameters:
  • header – the column header label
  • index – the column index to insert before
  • fill – the data to fill the column with (list or string)
add_row(row, index=None)

Insert a row at a specific index (default is to append)

Parameters:
  • row – the row data
  • index – the index to insert before
column_index(header)

Get the index of a column header in the table

column_indices(headers)

Get the indices of column headers in the table

columns(include_headers=True, include_empty=True)

(generator) Gives all columns in the table, optionally including headers or removing empty columns.

Parameters:
  • include_headers – include column headers
  • include_empty – include empty columns in the result
static from_columns(columns, headers=None, **kwargs)

(static method) Create a SimpleTable from column data

Parameters:
  • columns – the column data
  • headers – the headers (if None, the first entry of each column is used)

kwargs are passed onto the table constructor

static from_rows(rows, headers=None, **kwargs)

(static method) Create a SimpleTable from row data

Parameters:
  • rows – the row data
  • headers – the headers (if None, the first row is used)

kwargs are passed onto the table constructor

get_rows(skip_columns=None)

All of the row data, including the header row

headers

The column headers [list]

insert_row(row, index=None)

Insert a row at a specific index (default is to append)

Parameters:
  • row – the row data
  • index – the index to insert before
print_(min_col_width=5, format_str=u'{:>%d}', f=<open file '<stdout>', mode 'w' at 0x40294078>, delimiter=u' ', first_column_format=None, include_empty=False)

Print the table to a stream (default: stdout) with a specific format

Parameters:
  • min_col_width – minimum column width (spaces)
  • format_str – the format string to use with str.format() defaults to right-aligned columns
  • f – the file/stream to output to (requires write method)
  • delimeter – the delimeter to print between columns
  • first_column_format – the first column can optionally have a different format
  • include_empty – display empty columns
remove_column_by_index(idx)

Remove a column by index

remove_columns_by_index(indices)

Remove multiple columns by index

remove_empty_columns()

Remove all empty columns

remove_row(idx)

Remove a row by index

rows

All of the row data, including the header row

ecli_util.spvinfo – Structured PV info

Note

(TODO) this needs to be converted to a SimpleTable someday

ecli_util.spvinfo.format_structured_pv_info(d, level_indent=u' ', format_=u'%.4g', value_delimiter=u' ', column_headers=[])

Format the pv info from get_structured_pv_info(), for usage with print_table

ecli_util.spvinfo.get_structured_pv_info(dict_, prefix='', timeout=None, t_start=None, fail_on_error=False)

For a dictionary like the following with a prefix of ‘PV’:

get_structured_pv_info(
    { 'User' : {
        'High' : '.HLM',
        'Current' : '.RBV',
        'Low' : '.LLM',
         } ,
    }, prefix='PV')

The result would look like:

{
    'User' : {
        'High' : 2.0,     # <-- caget PV.HLM = 2.0
        'Current' : 1.0,  # <-- caget PV.RBV = 1.0
        'Low' : 0.0,      # <-- caget PV.RBV = 0.0
     } ,
}

prefix can also be a list (or sequence), and the result would then be:

return {
        'User' : {
            'High' : [1, 2, 3, ...]
                 }
       }
ecli_util.spvinfo.print_structured_pv_info(d, first_column_format=u'{:<%d}', f=<open file '<stdout>', mode 'w' at 0x40294078>, **kwargs)

Print the structured pv info in a table