Metadata-Version: 2.4
Name: specpy
Version: 2026.20.24464
Summary: Python Interface for Imspector
Author-email: Abberior Instruments GmbH <support@abberior-instruments.com>
License-Expression: BSD-3-Clause
Project-URL: Homepage, https://imspector.abberior-instruments.com
Keywords: Imspector
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering
Classifier: Programming Language :: C++
Classifier: Programming Language :: Python
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Requires-Python: >=3.7
Description-Content-Type: text/x-rst
Requires-Dist: numpy>=2.0.2
Dynamic: requires-dist

.. _specpy_:

==========================
Imspector Python Interface
==========================

.. role:: python(code)

Imspector comes with a Python Interface named SpecPy which can be used either
from the embedded Python console or from an external Python console running on
the same computer (to enable sharing of measurement data) or even running on a
different computer.

It can be used for remote control of microscopes, reading/writing data from/to
running Imspector instances, and subscribing to change notifications. Essentially,
all Imspector settings can be read and manipulated.

It can also be used as a standalone file reader to read .obf and .msr files in
Python.

--------------------
Start
--------------------

- Working from an external Python console you need to start the Imspector
  Server (which requires Administrator privileges the first time)

- To load the Python Interface just say

.. code-block:: python

  from specpy import *

--------------------
Examples
--------------------


Open an .obf file in Python without Imspector running.

.. code-block:: python

  import specpy as sp
  import numpy as np
  from matplotlib import pyplot as plt

  file = sp.File(r"C:\path\to\your\file.obf", sp.File.Read)

  number_of_stacks = file.number_of_stacks()
  metadata = file.metadata()

  for i_stack in range(number_of_stacks):
      stack = file.read(i_stack)
      stack_name = stack.name()
      stack_data = stack.data()
      
      if stack_data.dtype == "uint16":
          fig, ax = plt.subplots()
          ax.set_title(stack_name)
          ax.imshow(stack_data)


Remote control an Imspector instance to open a Stack and calculate some statistics

.. code-block:: python

  import specpy as sp
  import numpy as np

  imspector = sp.get_application()
  measurement = imspector.open(r"C:\path\to\your\file.obf")

  threshold = 410

  for name in measurement.stack_names():
    stack = measurement.stack(name)
    data = stack.data()

    mean = data.mean()
    standard_deviation = data.std()
    print(name, mean, standard_deviation)

    masked_data = np.ma.masked_less(data, threshold)
    mean = masked_data.mean()
    standard_deviation = masked_data.std()
    print(name, mean, standard_deviation)
    
    np.putmask(data, data < threshold, 4095)
    measurement.update()  # Update Imspector display after modifying stack data

--------------------
Interface
--------------------

Imspector
====================

.. code-block:: python

  get_application()

first tries to return the local Imspector object (living in the same process)
or else returns a proxy Imspector object connected to the Imspector
Application running on `localhost`.

.. code-block:: python

  get_application(host)

where :code:`host` is a host name returns a proxy Imspector object connected
to the Imspector Application running on the corresponding host.

If :code:`imspector` is an Imspector object then

.. code-block:: python

  imspector.host()

returns the name of the host the Imspector Application is running on or an
empty string in case the Imspector object is local (living in the same process),

.. code-block:: python

  imspector.version()

returns the current Imspector version,

.. code-block:: python

  imspector.device_drivers()

returns the Imspector device drivers as a dictionary of name value pairs,

.. code-block:: python

  imspector.value_at(path, specpy.ValueTree.Hardware).get()

where :code:`path` is of the form `device/.../parameter_name` returns the
corresponding Imspector parameter value (the empty path returns a dictionary of
name value pairs of all parameters).

.. code-block:: python

  imspector.value_at(path, specpy.ValueTree.Hardware).set(value)

where :code:`path` is of the form `device/.../parameter_name` and :code:`value`
is a value, sets the corresponding Imspector parameter value (the empty path
sets a dictionary of name value pairs of all parameters).

.. code-block:: python

  imspector.value_at(path, specpy.ValueTree.Status).get()

where :code:`path` is of the form `device/.../state_name` returns the
corresponding Imspector state value (the empty path returns a dictionary of
name value pairs of all states).

.. code-block:: python

  imspector.value_at(path, specpy.ValueTree.Status).set(value)

where :code:`path` is of the form `device/.../state_name` and :code:`value`
is a value, sets the corresponding Imspector state value (the empty path
sets a dictionary of name value pairs of all states).

.. code-block:: python

  imspector.measurement_names()

returns the list of names of all open measurements in Imspector,

.. code-block:: python

  imspector.active_measurement()

for the currently active measurement in Imspector, returns the corresponding
Measurement object or throws a RuntimeError if no measurement is active,

.. code-block:: python

  imspector.measurement(name)

where :code:`name` is the name of an open measurement in Imspector, returns the
corresponding Measurement object,

.. code-block:: python

  imspector.create_measurement()

creates an empty measurement in Imspector and returns the corresponding
Measurement object,

.. code-block:: python

  imspector.open(path)

where :code:`path` is the path to a measurement file, opens it in Imspector (if it is not already open) and
returns the corresponding Measurement object,

.. code-block:: python

  imspector.activate(measurement)

where :code:`measurement` is a Measurement object, activates the corresponding
measurement in Imspector,

.. code-block:: python

  imspector.start(measurement)

where :code:`measurement` is a Measurement object, starts the corresponding
measurement in Imspector and returns immediately,

.. code-block:: python

  imspector.pause(measurement)

where :code:`measurement` is a Measurement object, pauses the corresponding
measurement in Imspector,

.. code-block:: python

  imspector.run(measurement)

where :code:`measurement` is a Measurement object, runs the corresponding
measurement in Imspector (starts it and returns when it has finished),

.. code-block:: python

  imspector.close(measurement)

where :code:`measurement` is a Measurement object, closes the corresponding
measurement in Imspector,

.. code-block:: python

  imspector.active_stack()

for the currently active stack (from the currently active measurement) in
Imspector, returns the corresponding Stack object or throws a RuntimeError if no stack is active,

.. code-block:: python

  imspector.connect_measurement_cb(callable, signal)

where :code:`callable` is a callable Python object and :code:`signal` is one
of :code:`specpy.MeasurementSignal.beg_measurement`,
:code:`specpy.MeasurementSignal.end_measurement`,
:code:`specpy.MeasurementSignal.beg_step`, or
:code:`specpy.MeasurementSignal.end_step`, connects the callable to the
corresponding signal in Imspector,

.. code-block:: python

  imspector.disconnect_measurement_cb(callable, signal)

where :code:`callable` is a callable Python object and :code:`signal` is one
of :code:`specpy.MeasurementSignal.beg_measurement`,
:code:`specpy.MeasurementSignal.end_measurement`,
:code:`specpy.MeasurementSignal.beg_step`, or
:code:`specpy.MeasurementSignal.end_step`, disconnects the callable from the
corresponding signal in Imspector.

Measurement
====================

If :code:`measurement` is a Measurement object then

.. code-block:: python

  measurement.name()

returns the name of the measurement,

.. code-block:: python

  measurement.number_of_configurations()

returns the number of configurations in the measurement,

.. code-block:: python

  measurement.configuration_names()

returns the list of names of all configurations in the measurement,

.. code-block:: python

  measurement.active_configuration()

for the currently active configuration in the measurement, returns the
corresponding Configuration object,

.. code-block:: python

  measurement.configuration(position)

where :code:`position` is in the range from zero to the number of
configurations in the measurement minus one, returns the corresponding
Configuration object,

.. code-block:: python

  measurement.configuration(name)

where :code:`name` is one of the configuration names in the measurement,
returns the corresponding Configuration object,

.. code-block:: python

  measurement.activate(configuration)

where :code:`configuration` is a Configuration object, activates the
corresponding configuration in the measurement (if the measurement contains only one configuration, this configuration is activated by default),

.. code-block:: python

  measurement.clone(configuration)

where :code:`configuration` is a Configuration object, clones the
corresponding configuration in the measurement and activates and returns the
clone,

.. code-block:: python

  measurement.remove(configuration)

where :code:`configuration` is a Configuration object, removes the
corresponding configuration in the measurement,

.. code-block:: python

  measurement.parameters(path)

where :code:`path` is of the form `device/.../parameter_name` returns the
corresponding measurement parameter value for the currently active
configuration (the empty path returns a dictionary of name value pairs of all
parameters),

.. code-block:: python

  measurement.set_parameters(path, value)

where :code:`path` is of the form `device/.../parameter_name` and :code:`value`
is a value, sets the corresponding measurement parameter value for the
currently active configuration (the empty path sets a dictionary of name value
pairs of all parameters),

.. code-block:: python

  measurement.number_of_stacks()

returns the number of stacks in the measurement,

.. code-block:: python

  measurement.stack_names()

returns the list of names of all stacks in the measurement,

.. code-block:: python

  measurement.stack(position)

where :code:`position` is in the range from zero to the number of stacks in the
measurement minus one, returns the corresponding Stack object,

.. code-block:: python

  measurement.stack(name)

where :code:`name` is one of the stack names in the measurement, returns
the corresponding Stack object,

.. code-block:: python

  measurement.create_stack(type, sizes)

where :code:`type` is a NumPy `array data type <http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html#specifying-and-constructing-data-types>`_
and :code:`sizes` is a list of exactly four sizes of dimensions, creates a new
stack and returns the corresponding Stack object,

.. code-block:: python

  measurement.update()

redraws all corresponding stacks in Imspector
(useful when the stack content was changed from Python),

.. code-block:: python

  measurement.save_as(path[, compression])

where :code:`path` is a file path and :code:`compression` is :code:`True` by
default or :code:`False` saves it into a file.

Configuration
====================

If :code:`configuration` is a Configuration object then

.. code-block:: python

  configuration.name()

returns the name of the configuration,

.. code-block:: python

  configuration.parameters(path)

where :code:`path` is of the form `device/.../parameter_name` returns the
corresponding measurement parameter value for this configuration (the empty
path returns a dictionary of name value pairs of all parameters),

.. code-block:: python

  configuration.set_parameters(path, value)

where :code:`path` is of the form `device/.../parameter_name` and :code:`value`
is a value, sets the corresponding measurement parameter value for this
configuration (the empty path sets a dictionary of name value pairs of all
parameters),

.. code-block:: python

  configuration.number_of_stacks()

returns the number of stacks in this configuration,

.. code-block:: python

  configuration.stack_names()

returns the list of names of all stacks in this configuration,

.. code-block:: python

  configuration.stack(position)

where :code:`position` is in the range from zero to the number of stacks in the
configuration minus one, returns the corresponding Stack object,

.. code-block:: python

  configuration.stack(name)

where :code:`name` is one of the stack names in this configuration, returns
the corresponding Stack object.

File
====================

.. code-block:: python

  File(path, mode)

where :code:`path` is the path to an `.obf` or `.msr` file and :code:`mode` is
either :code:`File.Read` or :code:`File.Write` or :code:`File.Append` opens it
and returns the corresponding File object.

If :code:`file` is a File object then

.. code-block:: python

  file.description()

returns the description of the file,

.. code-block:: python

  file.set_description(string)

where :code:`string` is a string sets the description of the file,

.. code-block:: python

  file.number_of_stacks()

returns the number of stacks in the file,

.. code-block:: python

  file.read(position)

where :code:`position` is in the range from zero to the number of stacks in the
file minus one, reads and returns the corresponding Stack object,

.. code-block:: python

  file.write(stack[, compression])

where :code:`stack` is a Stack object and :code:`compression` is :code:`True`
by default or :code:`False` writes it to the file,

.. code-block:: python

  del file

closes the file.

Stack
====================

.. code-block:: python

  Stack(array)

where :code:`array` is a NumPy `ndarray <http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html>`_ returns a
new local Stack object with data values from the array.

.. code-block:: python

  Stack(type, sizes)

where :code:`type` is a NumPy `array data type <http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html#specifying-and-constructing-data-types>`_
and :code:`sizes` is a list of sizes of all dimensions returns a new local
Stack object.

If :code:`stack` is a Stack object then

.. code-block:: python

  stack.name()

returns the name of the stack,

.. code-block:: python

  stack.set_name(string)

where :code:`string` is a string sets the name of the stack. If another stack in the same measurement already has the same name, suffixes of the form [1], [2], .. are added.

.. code-block:: python

  stack.description()

returns the description of the stack,

.. code-block:: python

  stack.set_description(string)

where :code:`string` is a string, sets the description of the stack,

.. code-block:: python

  stack.type()

returns the type of the stack elements as NumPy `array data type <http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html#specifying-and-constructing-data-types>`_,

.. code-block:: python

  stack.number_of_elements()

returns the number of elements of the stack,

.. code-block:: python

  stack.shape()

returns the list of sizes of all dimensions of the stack,

.. code-block:: python

  stack.label(dimension)

where :code:`dimension` is one of the dimensions returns the corresponding
label of the stack,

.. code-block:: python

  stack.set_label(dimension, string)

where :code:`dimension` is one of the dimensions and :code:`string` is a string
sets the corresponding label of the stack,

.. code-block:: python

  stack.labels()

returns the list of labels of all dimensions of the stack,

.. code-block:: python

  stack.set_labels(strings)

where :code:`strings` is a list of strings for all dimensions sets the
corresponding labels of the stack,

.. code-block:: python

  stack.length(dimension)

where :code:`dimension` is one of the dimensions returns the corresponding
length of the stack,

.. code-block:: python

  stack.set_length(dimension, number)

where :code:`dimension` is one of the dimensions and :code:`number` is a number
sets the corresponding length of the stack,

.. code-block:: python

  stack.lengths()

returns the list of lengths of all dimensions of the stack,

.. code-block:: python

  stack.set_lengths(numbers)

where :code:`numbers` is a list of numbers for all dimensions sets the
corresponding lengths of the stack,

.. code-block:: python

  stack.offset(dimension)

where :code:`dimension` is one of the dimensions returns the corresponding
offset of the stack,

.. code-block:: python

  stack.set_offset(dimension, number)

where :code:`dimension` is one of the dimensions and :code:`number` is a number
sets the corresponding offset of the stack,

.. code-block:: python

  stack.offsets()

returns the list of offsets of all dimensions of the stack,

.. code-block:: python

  stack.set_offsets(numbers)

where :code:`numbers` is a list of numbers for all dimensions sets the
corresponding offsets of the stack,

.. code-block:: python

  stack.parameters(path)

where :code:`path` is of the form `.../parameter_name` returns the
corresponding stack parameter value (the empty path returns a dictionary of
name value pairs of all parameters),

.. code-block:: python

  stack.data()

returns the data of the stack as a NumPy `ndarray <http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html>`_.
