# specplot¶

Read a SPEC data file and plot a thumbnail image.

This code can be called as a standalone program or it can be imported into another program and called as a subroutine, as shown in the specplot_gallery program.

The standard representation of a SPEC scan is a line plot of the last data column versus the first data column. Any SPEC macro which name ends with scan ([1]) will be plotted as a line plot.

A special case SPEC scan macro is the hklscan where one of the three reciprocal space axes is scanned while the other two remain constant. A special handler (SPEC’s hklscan macro) is provided to pick properly the scanned axis (not always the first column) for representation as a line plot.

Some SPEC macros scan two positioners over a grid to collect a 2-D image one pixel at a time. These scans are represented as color-mapped images where the first two columns are the vertical and horizontal axes and the image is color-mapped to intensity. Any SPEC macro which name ends with mesh will be plotted as an image plot.

 [1] scan: any scan where the last four letters converted to lower case match scan, such as ascan, a2scan, Escan, tscan, uascan, FlyScan, unusual_custom_user_scan, …

Different handling can be customized for scan macros, as described in How to write a custom scan handling for specplot.

## How to use specplot¶

Plot a scan from one of the sample data files supplied with spec2nexus:

user@host ~$specplot src/spec2nexus/data/APS_spec_data.dat 2 specplot.png  ## Usage¶ user@host ~$ specplot
usage: specplot.py [-h] specFile scan_number plotFile


## Help¶

user@host ~\$ specplot -h
usage: specplot.py [-h] specFile scan_number plotFile

read a SPEC data file and plot scan n

positional arguments:
specFile     SPEC data file name
scan_number  scan number in SPEC file
plotFile     output plot file name

optional arguments:
-h, --help   show this help message and exit


### source code documentation¶

Plot the data from scan N in a SPEC data file

 Selector() associate SPEC scan macro names with image makers ImageMaker() superclass to handle plotting of data from a SPEC scan LinePlotter() create a line plot MeshPlotter() create a mesh plot (2-D image) openSpecFile(specFile) convenience routine so that others do not have to import spec2nexus.spec

Exceptions:

 NoDataToPlot No data found. NotPlottable No plottable data for this scan. ScanAborted Scan aborted before all points acquired. UnexpectedObjectTypeError Incorrect Python object type: programmer error.
class spec2nexus.specplot.HKLScanPlotter[source]

create a line plot from hklscan macros

retrieve_plot_data()[source]

retrieve default data from spec data file

class spec2nexus.specplot.ImageMaker[source]

superclass to handle plotting of data from a SPEC scan

Internal data model

Signal: name of the signal data (default data to be plotted) values of various collected arrays {label: array} names of the axes of signal data

USAGE:

1. Create a subclass of ImageMaker

2. Override any of these methods:

 data_file_name() the name of the file with the actual data make_image(plotFile) make MatPlotLib chart image from the SPEC scan plottable() can this data be plotted as expected? plot_options() re-define any plot options in a subclass retrieve_plot_data() retrieve default plottable data from spec data file and store locally

EXAMPLE

class LinePlotter(ImageMaker):
'''create a line plot'''

def make_image(self, plotFile):
'''
make MatPlotLib chart image from the SPEC scan

:param obj plotData: object returned from :meth:retrieve_plot_data
:param str plotFile: name of image file to write
'''
assert(self.signal in self.data)
assert(len(self.axes) == 1)
assert(self.axes[0] in self.data)

y = self.data[self.signal]
x = self.data[self.axes[0]]
xy_plot(x, y,  plotFile,
title = self.plot_title(),
plot_subtitle = self.plot_subtitle(),
xtitle = self.x_title(),
ytitle = self.y_title(),
xlog = self.x_log(),
ylog = self.y_log(),
timestamp_str = self.timestamp())

sfile = specplot.openSpecFile(specFile)
scan = sfile.getScan(scan_number)
plotter = LinePlotter()
plotter.plot_scan(scan, plotFile, y_log=True)

data_file_name()[source]

the name of the file with the actual data

Usually, this is the SPEC data file but it could be something else

data_is_newer_than_plot(plotFile)[source]

only proceed if mtime of SPEC data file is newer than plotFile

make_image(plotFile)[source]

make MatPlotLib chart image from the SPEC scan

The data to be plotted are provided in:

• self.signal
• self.axes
• self.data
Parameters: plotFile (str) – name of image file to write
plot_options()[source]

re-define any plot options in a subclass

plot_scan(scan, plotFile, maker=None)[source]

make an image plot of the data in the scan

Parameters: scan (obj) – instance of SpecDataFileScan plotFile (str) – file name for plot output
plot_subtitle()[source]

Return the plot_subtitle.

plot_title()[source]

Return the plot title.

plottable()[source]

can this data be plotted as expected?

retrieve_plot_data()[source]

retrieve default plottable data from spec data file and store locally

This method must retrieve the data to be plotted, either from the SPEC data file scan or from a file which name is provided in the scan detalis.

These attributes must be set by this method:

Data: dictionary containing values of the various collected arrays {label: array} name of the ‘signal’ data (default data to be plotted) names of the axes of signal data

Example data

self.data = {
'angle': [1, 2, 3, 4, 5],
'counts': [0. 2. 55. 3. 0]}
self.signal = 'counts'
self.axes = ['angle']


Raise any of these exceptions as appropriate:

 NoDataToPlot No data found. NotPlottable No plottable data for this scan. ScanAborted Scan aborted before all points acquired.
set_plot_subtitle(text)[source]

Set the plot_subtitle.

set_plot_title(text)[source]

Set the plot title.

set_timestamp(text)[source]

Set the plot time stamp.

set_x_log(choice)[source]

Set the x axis logarithmic if True.

set_x_title(text)[source]

Set the x axis title.

set_y_log(choice)[source]

Set the y axis logarithmic if True.

set_y_title(text)[source]

Set the y axis title.

set_z_log(choice)[source]

Set the z axis (image) logarithmic if True.

timestamp()[source]

Return the time of this scan as a string.

x_log()[source]

Boolean: should the X axis be plotted on a log scale?

x_title()[source]

Return the title for the X axis.

y_log()[source]

Boolean: should the Y axis be plotted on a log scale?

y_title()[source]

Return the title for the Y axis.

z_log()[source]

Boolean: should the Z axis (image) be plotted on a log scale?

class spec2nexus.specplot.LinePlotter[source]

create a line plot

make_image(plotFile)[source]

make MatPlotLib chart image from the SPEC scan

Parameters: plotFile (str) – name of image file to write
plot_options()[source]

define the settings for this, accepting any non-default values first

plottable()[source]

can this data be plotted as expected?

retrieve_plot_data()[source]

retrieve default data from spec data file

class spec2nexus.specplot.MeshPlotter[source]

create a mesh plot (2-D image)

..rubric:: References:

Mesh 2-D parser:

http://www.certif.com/spec_help/mesh.html

mesh motor1 start1 end1 intervals1 motor2 start2 end2 intervals2 time

Hklmesh 2-D parser:

http://www.certif.com/spec_help/hklmesh.html

hklmesh Q1 start1 end1 intervals1 Q2 start2 end2 intervals2 time

make_image(plotFile)[source]

make MatPlotLib chart image from the SPEC scan

Parameters: plotFile (str) – name of image file to write
plot_options()[source]

define the settings for this, accepting any non-default values first

plottable()[source]

can this data be plotted as expected?

retrieve_plot_data()[source]

retrieve default data from spec data file

data parser for 2-D mesh and hklmesh

exception spec2nexus.specplot.NoDataToPlot[source]

No data found.

exception spec2nexus.specplot.NotPlottable[source]

No plottable data for this scan.

exception spec2nexus.specplot.ScanAborted[source]

Scan aborted before all points acquired.

class spec2nexus.specplot.Selector[source]

associate SPEC scan macro names with image makers

Image maker: subclass of ImageMaker

To include a custom image maker from outside this module, create the subclass and then add it to an instance of this class. Such as this plotter that defaults to a logarithmic scale for the X axis for all logxscan macros:

from spec2nexus import specplot

class LogX_Plotter(specplot.ImageMaker):

def x_log(self):
return True

# …

# …

image_maker = specplot.Selector().auto(scan) plotter = image_maker() plotter.plot_scan(scan, fullPlotFile)

This class is a singleton which means you will always get the same instance when you call this class many times in your program.

 auto(scan) automatically choose a scan image maker based on the SPEC scan macro add(key, value[, default]) register a new value by key update(key, value[, default]) replace an existing key with a new value get(key) return a value by key exists(key) is the key known? default() retrieve the value of the default key
add(key, value, default=False)[source]

register a new value by key

Parameters: key (str) – name of key, typically the macro name KeyError – if key exists UnexpectedObjectTypeError – if value is not subclass of ImageMaker
auto(scan)[source]

automatically choose a scan image maker based on the SPEC scan macro

Selection Rules:

default()[source]

retrieve the value of the default key

exists(key)[source]

is the key known?

get(key)[source]

return a value by key

Returns: subclass of ImageMaker or None if key not found
update(key, value, default=False)[source]

replace an existing key with a new value

Parameters: key (str) – name of key, typically the macro name KeyError – if key does not exist UnexpectedObjectTypeError – if value is not subclass of ImageMaker
exception spec2nexus.specplot.UnexpectedObjectTypeError[source]

Incorrect Python object type: programmer error.

spec2nexus.specplot.openSpecFile(specFile)[source]

convenience routine so that others do not have to import spec2nexus.spec