Skip to main content
`Ctrl`+`K`

# `specfile`: Reading SpecFile

This module is a cython binding to wrap the C SpecFile library, to access SpecFile data within a python program.

Documentation for the original C library SpecFile can be found on the ESRF website: The manual for the SpecFile Library

## Examples

Start by importing `SpecFile` and instantiate it:

    from silx.io.specfile import SpecFile

    sf = SpecFile("test.dat")

A `SpecFile` instance can be accessed like a dictionary to obtain a `Scan` instance.

If the key is a string representing two values separated by a dot (e.g. `"1.2"`), they will be treated as the scan number (`#S` header line) and the scan order:

    # get second occurrence of scan "#S 1"
    myscan = sf["1.2"]

    # access scan data as a numpy array
    nlines, ncolumns = myscan.data.shape

If the key is an integer, it will be treated as a 0-based index:

    first_scan = sf[0]
    second_scan = sf[1]

It is also possible to browse through all scans using `SpecFile` as an iterator:

    for scan in sf:
        print(scan.scan_header_dict['S'])

MCA spectra can be selectively loaded using an instance of `MCA` provided by `Scan`:

    # Only one MCA spectrum is loaded in memory
    second_mca = first_scan.mca[1]

    # Iterating trough all MCA spectra in a scan:
    for mca_data in first_scan.mca:
        print(sum(mca_data))

## Classes

- `SpecFile`

- `Scan`

- `MCA`

## Exceptions

- `SfError`

- `SfErrMemoryAlloc`

- `SfErrFileOpen`

- `SfErrFileClose`

- `SfErrFileRead`

- `SfErrFileWrite`

- `SfErrLineNotFound`

- `SfErrScanNotFound`

- `SfErrHeaderNotFound`

- `SfErrLabelNotFound`

- `SfErrMotorNotFound`

- `SfErrPositionNotFound`

- `SfErrLineEmpty`

- `SfErrUserNotFound`

- `SfErrColNotFound`

- `SfErrMcaNotFound`

class SpecFile(filename)
  Parameters:

    filename – Path of the SpecFile to read

  This class wraps the main data and header access functions of the C SpecFile library.

  __len__(self)

    Return the number of scans in the SpecFile

  __iter__(self)

    Return the next `Scan` in a SpecFile each time this method is called.

    This usually happens when the python built-in function `next()` is called with a `SpecFile` instance as a parameter, or when a `SpecFile` instance is used as an iterator (e.g. in a `for` loop).

  __getitem__(self, key)

    Return a `Scan` object.

    This special method is called when a `SpecFile` instance is accessed as a dictionary (e.g. `sf[key]`).

    Parameters:

      key (int or str) – 0-based scan index or `"n.m"` key, where `n` is the scan number defined on the `#S` header line and `m` is the order

    Returns:

      Scan defined by its 0-based index or its `"n.m"` key

    Return type:

      `Scan`

  close(self)

    Close the file descriptor

  columns(self, scan_index)

    Return number of columns in a scan from the `#N` header line (without `#N` and scan number)

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.

    Returns:

      Number of columns in scan from `#N` line

    Return type:

      int

  command(self, scan_index)

    Return `#S` line (without `#S` and scan number)

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.

    Returns:

      S line

    Return type:

      str

  data(self, scan_index)

    Returns data for the specified scan index.

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.

    Returns:

      Complete scan data as a 2D array of doubles

    Return type:

      numpy.ndarray

  data_column_by_name(self, scan_index, label)

    Returns data column for the specified scan index and column label.

    Parameters:

      - scan_index (int) – Unique scan index between `0` and `len(self)-1`.

      - label (str) – Label of data column, as defined in the `#L` line of the scan header.

    Returns:

      Data column as a 1D array of doubles

    Return type:

      numpy.ndarray

  date(self, scan_index=0)

    Return date from `#D` line

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.

    Returns:

      Date from `#D` line

    Return type:

      str

  file_header(self, scan_index=0)

    Return list of file header lines.

    A file header contains all lines between a `#F` header line and a `#S` header line (start of scan). We need to specify a scan number because there can be more than one file header in a given file. A file header applies to all subsequent scans, until a new file header is defined.

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.

    Returns:

      List of raw file header lines

    Return type:

      list of str

  get_mca(self, scan_index, mca_index)

    Return one MCA spectrum

    Parameters:

      - scan_index (int) – Unique scan index between `0` and `len(self)-1`.

      - mca_index (int) – Index of MCA in the scan

    Returns:

      MCA spectrum

    Return type:

      1D numpy array

  index(self, scan_number, scan_order=1)

    Returns scan index from scan number and order.

    Parameters:

      - scan_number (int) – Scan number (possibly non-unique).

      - scan_order (int default 1) – Scan order.

    Returns:

      Unique scan index

    Return type:

      int

    Scan indices are increasing from `0` to `len(self)-1` in the order in which they appear in the file. Scan numbers are defined by users and are not necessarily unique. The scan order for a given scan number increments each time the scan number appears in a given file.

  keys(self)

    Returns list of scan keys (eg `['1.1', '2.1',...]`).

    Returns:

      list of scan keys

    Return type:

      list of strings

  labels(self, scan_index)

    Return all labels from `#L` line

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.

    Returns:

      All labels from `#L` line

    Return type:

      list of strings

  list(self)

    Returns list (1D numpy array) of scan numbers in SpecFile.

    Returns:

      list of scan numbers (from `` #S`` lines) in the same order as in the original SpecFile (e.g `[1, 1, 2, 3, …]`).

    Return type:

      numpy array

  mca_calibration(self, scan_index)

    Return MCA calibration in the form \(a + b x + c x²\)

    Raise a KeyError if there is no `@CALIB` line in the scan header.

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.

    Returns:

      MCA calibration as a list of 3 values \((a, b, c)\)

    Return type:

      list of floats

  motor_names(self, scan_index=0)

    Return all motor names from `#O` lines

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.If not specified, defaults to 0 (meaning the function returns motors names associated with the first scan). This parameter makes a difference only if there are more than on file header in the file, in which case the file header applies to all following scans until a new file header appears.

    Returns:

      All motor names

    Return type:

      list of strings

  motor_position_by_name(self, scan_index, name)

    Return motor position

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.

    Returns:

      Specified motor position

    Return type:

      double

  motor_positions(self, scan_index)

    Return all motor positions

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.

    Returns:

      All motor positions

    Return type:

      list of double

  number(self, scan_index)

    Returns scan number from scan index.

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.

    Returns:

      User defined scan number.

    Return type:

      int

  number_of_mca(self, scan_index)

    Return number of mca spectra in a scan.

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.

    Returns:

      Number of mca spectra.

    Return type:

      int

  order(self, scan_index)

    Returns scan order from scan index.

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.

    Returns:

      Scan order (sequential number incrementing each time a non-unique occurrence of a scan number is encountered).

    Return type:

      int

  scan_header(self, scan_index)

    Return list of scan header lines.

    Parameters:

      scan_index (int) – Unique scan index between `0` and `len(self)-1`.

    Returns:

      List of raw scan header lines

    Return type:

      list of str

class Scan(specfile, scan_index)
  Parameters:

    - specfile (`SpecFile`) – Parent SpecFile from which this scan is extracted.

    - scan_index (int) – Unique index defining the scan in the SpecFile

  Interface to access a SpecFile scan

  A scan is a block of descriptive header lines followed by a 2D data array.

  Following three ways of accessing a scan are equivalent:

      sf = SpecFile("/path/to/specfile.dat")

      # Explicit class instantiation
      scan2 = Scan(sf, scan_index=2)

      # 0-based index on a SpecFile object
      scan2 = sf[2]

      # Using a "n.m" key (scan number starting with 1, scan order)
      scan2 = sf["3.1"]

  property data

    Scan data as a 2D numpy.ndarray with the usual attributes (e.g. data.shape).

    The first index is the detector, the second index is the sample index.

  data_column_by_name(self, label)

    Returns a data column

    Parameters:

      label (str) – Label of data column to retrieve, as defined on the `#L` line of the scan header.

    Returns:

      Line data as a 1D array of doubles

    Return type:

      numpy.ndarray

  data_line(self, line_index)

    Returns data for a given line of this scan.

    Note

    A data line returned by this method, corresponds to a data line in the original specfile (a series of data points, one per detector). In the `data` array, this line index corresponds to the index in the second dimension (~ column) of the array.

    Parameters:

      line_index (int) – Index of data line to retrieve (starting with 0)

    Returns:

      Line data as a 1D array of doubles

    Return type:

      numpy.ndarray

  property file_header

    List of raw file header lines (as a list of strings).

  property file_header_dict

    Dictionary of file header strings, keys without the leading `#` (e.g. `file_header_dict["F"]`).

  property header

    List of raw header lines (as a list of strings).

    This includes the file header, the scan header and possibly a MCA header.

  property index

    Unique scan index 0 - len(specfile)-1

    This attribute is implemented as a read-only property as changing its value may cause nasty side-effects (such as loading data from a different scan without updating the header accordingly.

  property labels

    List of data column headers from `#L` scan header

  property mca

    MCA data in this scan.

    Each multichannel analysis is a 1D numpy array. Metadata about MCA data is to be found in `mca_header`.

    Return type:

      `MCA`

  property mca_header_dict

    Dictionary of MCA header strings, keys without the leading `#@` (e.g. `mca_header_dict["CALIB"]`).

  property motor_names

    List of motor names from the `#O` file header line.

  motor_position_by_name(self, name)

    Returns the position for a given motor

    Parameters:

      name (str) – Name of motor, as defined on the `#O` line of the file header.

    Returns:

      Motor position

    Return type:

      float

  property motor_positions

    List of motor positions as floats from the `#P` scan header line.

  property number

    First value on #S line (as int)

  property order

    Order can be > 1 if the same number is repeated in a specfile

  record_exists_in_hdr(self, record)

    Check whether a scan header line exists.

    This should be used before attempting to retrieve header information using a C function that may crash with a segmentation fault if the header isn’t defined in the SpecFile.

    Parameters:

      record (str) – single upper case letter corresponding to the header you want to test (e.g. `L` for labels)

    Returns:

      True or False

    Return type:

      boolean

  property scan_header

    List of raw scan header lines (as a list of strings).

  property scan_header_dict

    Dictionary of scan header strings, keys without the leading``#`` (e.g. `scan_header_dict["S"]`). Note: this does not include MCA header lines starting with `#@`.

class MCA(scan)
  Parameters:

    scan (`Scan`) – Parent Scan instance

  Variables:

    - calibration – MCA calibration \((a, b, c)\) (as in \(a + b x + c x²\)) from `#@CALIB` scan header.

    - channels – MCA channels list from `#@CHANN` scan header. In the absence of a `#@CHANN` header, this attribute is a list `[0, …, N-1]` where `N` is the length of the first spectrum. In the absence of MCA spectra, this attribute defaults to `None`.

  This class provides access to Multi-Channel Analysis data. A `MCA` instance can be indexed to access 1D numpy arrays representing single MCA spectra.

  To create a `MCA` instance, you must provide a parent `Scan` instance, which in turn will provide a reference to the original `SpecFile` instance:

      sf = SpecFile("/path/to/specfile.dat")
      scan2 = Scan(sf, scan_index=2)
      mcas_in_scan2 = MCA(scan2)
      for i in len(mcas_in_scan2):
          mca_data = mcas_in_scan2[i]
          ... # do some something with mca_data (1D numpy array)

  A more pythonic way to do the same work, without having to explicitly instantiate `scan` and `mcas_in_scan`, would be:

      sf = SpecFile("specfilename.dat")
      # scan2 from previous example can be referred to as sf[2]
      # mcas_in_scan2 from previous example can be referred to as scan2.mca
      for mca_data in sf[2].mca:
          ... # do some something with mca_data (1D numpy array)

  __len__(self)
    Returns:

      Number of mca in Scan

    Return type:

      int

  __iter__(self)

    Return the next MCA data line each time this method is called.

    Returns:

      Single MCA

    Return type:

      1D numpy array

  __getitem__(self, key)

    Return a single MCA data line

    Parameters:

      key (int) – 0-based index of MCA within Scan

    Returns:

      Single MCA

    Return type:

      1D numpy array

class SfError

  Base exception inherited by all exceptions raised when a C function from the legacy SpecFile library returns an error code.

class SfErrMemoryAlloc

  Bases: `SfError`, `MemoryError`

class SfErrFileOpen

  Bases: `SfError`, `OSError`

class SfErrFileClose

  Bases: `SfError`, `OSError`

class SfErrFileRead

  Bases: `SfError`, `OSError`

class SfErrFileWrite

  Bases: `SfError`, `OSError`

class SfErrLineNotFound

  Bases: `SfError`, `KeyError`

class SfErrScanNotFound

  Bases: `SfError`, `IndexError`

class SfErrHeaderNotFound

  Bases: `SfError`, `KeyError`

class SfErrLabelNotFound

  Bases: `SfError`, `KeyError`

class SfErrMotorNotFound

  Bases: `SfError`, `KeyError`

class SfErrPositionNotFound

  Bases: `SfError`, `KeyError`

class SfErrLineEmpty

  Bases: `SfError`, `OSError`

class SfErrUserNotFound

  Bases: `SfError`, `KeyError`

class SfErrColNotFound

  Bases: `SfError`, `KeyError`

class SfErrMcaNotFound

  Bases: `SfError`, `IndexError`

class SfNoMcaError

  Bases: `SfError`

  Custom exception raised when `SfNoMca()` returns `-1`