diff --git a/doc/source/apiref/yokogawa.rst b/doc/source/apiref/yokogawa.rst index 372ffd223..7dcd32589 100644 --- a/doc/source/apiref/yokogawa.rst +++ b/doc/source/apiref/yokogawa.rst @@ -7,6 +7,13 @@ Yokogawa ======== +:class:`Yokogawa6370` Optical Spectrum Analyzer +=============================================== + +.. autoclass:: Yokogawa6370 + :members: + :undoc-members: + :class:`Yokogawa7651` Power Supply ================================== diff --git a/instruments/abstract_instruments/__init__.py b/instruments/abstract_instruments/__init__.py index 7b7eea482..390473b74 100644 --- a/instruments/abstract_instruments/__init__.py +++ b/instruments/abstract_instruments/__init__.py @@ -19,3 +19,8 @@ PowerSupplyChannel, PowerSupply, ) + +from .optical_spectrum_analyzer import ( + OSAChannel, + OpticalSpectrumAnalyzer, +) diff --git a/instruments/abstract_instruments/optical_spectrum_analyzer.py b/instruments/abstract_instruments/optical_spectrum_analyzer.py new file mode 100644 index 000000000..3cc9f4ab2 --- /dev/null +++ b/instruments/abstract_instruments/optical_spectrum_analyzer.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Provides an abstract base class for optical spectrum analyzer instruments +""" + +# IMPORTS ##################################################################### + +from __future__ import absolute_import +from __future__ import division + +import abc + +from future.utils import with_metaclass + +from instruments.abstract_instruments import Instrument + +# CLASSES ##################################################################### + + +class OSAChannel(with_metaclass(abc.ABCMeta, object)): + + """ + Abstract base class for physical channels on an optical spectrum analyzer. + + All applicable concrete instruments should inherit from this ABC to + provide a consistent interface to the user. + """ + + # METHODS # + + @abc.abstractmethod + def wavelength(self, bin_format=True): + """ + Gets the x-axis of the specified data source channel. This is an + abstract property. + + :param bool bin_format: If the waveform should be transfered in binary + (``True``) or ASCII (``False``) formats. + :return: The wavelength component of the waveform. + :rtype: `numpy.ndarray` + """ + raise NotImplementedError + + @abc.abstractmethod + def data(self, bin_format=True): + """ + Gets the y-axis of the specified data source channel. This is an + abstract property. + + :param bool bin_format: If the waveform should be transfered in binary + (``True``) or ASCII (``False``) formats. + :return: The y-component of the waveform. + :rtype: `numpy.ndarray` + """ + raise NotImplementedError + + +class OpticalSpectrumAnalyzer(with_metaclass(abc.ABCMeta, Instrument)): + + """ + Abstract base class for optical spectrum analyzer instruments. + + All applicable concrete instruments should inherit from this ABC to + provide a consistent interface to the user. + """ + + # PROPERTIES # + + @abc.abstractproperty + def channel(self): + """ + Gets an iterator or list for easy Pythonic access to the various + channel objects on the OSA instrument. Typically generated + by the `~instruments.util_fns.ProxyList` helper. + """ + raise NotImplementedError + + + @property + @abc.abstractmethod + def start_wl(self): + """ + Gets/sets the the start wavelength of the OSA. This is + an abstract property. + + :type: `~quantities.Quantity` + """ + raise NotImplementedError + + @start_wl.setter + @abc.abstractmethod + def start_wl(self, newval): + raise NotImplementedError + + @property + @abc.abstractmethod + def stop_wl(self): + """ + Gets/sets the the stop wavelength of the OSA. This is + an abstract property. + + :type: `~quantities.Quantity` + """ + raise NotImplementedError + + @stop_wl.setter + @abc.abstractmethod + def stop_wl(self, newval): + raise NotImplementedError + + @property + @abc.abstractmethod + def bandwidth(self): + """ + Gets/sets the the bandwidth of the OSA. This is + an abstract property. + + :type: `~quantities.Quantity` + """ + raise NotImplementedError + + @bandwidth.setter + @abc.abstractmethod + def bandwidth(self, newval): + raise NotImplementedError + + + # METHODS # + + @abc.abstractmethod + def start_sweep(self): + """ + Forces a start sweep on the attached OSA. + """ + raise NotImplementedError diff --git a/instruments/yokogawa/__init__.py b/instruments/yokogawa/__init__.py index fa7b6084f..75df60d4a 100644 --- a/instruments/yokogawa/__init__.py +++ b/instruments/yokogawa/__init__.py @@ -7,3 +7,4 @@ from __future__ import absolute_import from .yokogawa7651 import Yokogawa7651 +from .yokogawa6370 import Yokogawa6370 diff --git a/instruments/yokogawa/yokogawa6370.py b/instruments/yokogawa/yokogawa6370.py new file mode 100644 index 000000000..5a0060c4a --- /dev/null +++ b/instruments/yokogawa/yokogawa6370.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Provides support for the Yokogawa 6370 optical spectrum analyzer. +""" + +# IMPORTS ##################################################################### + +from __future__ import absolute_import +from __future__ import division + +from builtins import range +from enum import IntEnum, Enum + +import quantities as pq + +from instruments.abstract_instruments import ( + OpticalSpectrumAnalyzer, + OSAChannel, +) +from instruments.util_fns import ( + enum_property, unitful_property, unitless_property, + bounded_unitful_property, ProxyList +) + + +# CLASSES ##################################################################### + +class Yokogawa6370(OpticalSpectrumAnalyzer): + + """ + The Yokogawa 6370 is a optical spectrum analyzer. + + Example usage: + + >>> import instruments as ik + >>> import quantities as pq + >>> inst = ik.yokogawa.Yokogawa6370.open_visa('TCPIP0:192.168.0.35') + >>> inst.start_wl = 1030e-9 * pq.m + """ + + def __init__(self, *args, **kwargs): + super(Yokogawa6370, self).__init__(*args, **kwargs) + # Set data Format to binary + self.sendcmd(":FORMat:DATA REAL,64") # TODO: Find out where we want this + + # INNER CLASSES # + + class Channel(OSAChannel): + + """ + Class representing the channels on the Yokogawa 6370. + + This class inherits from `OSAChannel`. + + .. warning:: This class should NOT be manually created by the user. It + is designed to be initialized by the `Yokogawa6370` class. + """ + _trace_names = ["TRA", "TRB", "TRC", "TRD", "TRE", "TRF", "TRG"] + + def __init__(self, parent, idx): + self._parent = parent + self._name = self._trace_names[idx] + + # METHODS # + + def data(self, bin_format=True): + cmd = ":TRAC:Y? {0}".format(self._name) + self._parent.sendcmd(cmd) + data = self._parent.binblockread(data_width=4, fmt=">> import instruments as ik + >>> osa = ik.yokogawa.Yokogawa6370.open_gpibusb('/dev/ttyUSB0') + >>> dat = osa.channel[0].data # Gets the data of channel 0 + + :rtype: `list`[`~Yokogawa6370.Channel`] + """ + return ProxyList(self, Yokogawa6370.Channel, range(6)) + + start_wl, start_wl_min, start_wl_max = bounded_unitful_property( + ":SENS:WAV:STAR", + pq.meter, + doc=""" + The start wavelength in m. + """, + valid_range=(600e-9, 1700e-9) + ) + + stop_wl, stop_wl_min, stop_wl_max = bounded_unitful_property( + ":SENS:WAV:STOP", + pq.meter, + doc=""" + The stop wavelength in m. + """, + valid_range=(600e-9, 1700e-9) + ) + + bandwidth = unitful_property( + ":SENS:BAND:RES", + pq.meter, + doc=""" + The bandwidth in m. + """ + ) + + span = unitful_property( + ":SENS:WAV:SPAN", + pq.meter, + doc=""" + A floating point property that controls the wavelength span in m. + """ + ) + + center_wl = unitful_property( + ":SENS:WAV:CENT", + pq.meter, + doc=""" + A floating point property that controls the center wavelength m. + """ + ) + + points = unitless_property( + ":SENS:SWE:POIN", + doc=""" + An integer property that controls the number of points in a trace. + """ + ) + + sweep_mode = enum_property( + ":INIT:SMOD", + SweepModes, + input_decoration=int, + doc=""" + A property to control the Sweep Mode as oe of Yokogawa6370.SweepMode. + Effective only after a self.start_sweep().""" + ) + + active_trace = enum_property( + ":TRAC:ACTIVE", + Traces, + doc=""" + The active trace of the OSA of enum Yokogawa6370.Traces. Determines the + result of Yokogawa6370.data() and Yokogawa6370.wavelength().""" + ) + + # METHODS # + + def data(self): + """ + Function to query the active Trace data of the OSA. + """ + cmd = ":TRAC:Y? {0}".format(self.active_trace.value) + self.sendcmd(cmd) + data = self.binblockread(data_width=4, fmt="