Ocean Optics Multi-Channel Spectrometry Oddities
evantaylor opened this issue · 1 comments
spectrometer and system information
- model: Ocean Optics Jaz
- operating system: Any
- python version: 3.9.5
- python-seabreeze version: 1.3.0
- installed-via: pip
current problem
Ocean Optics Jaz Spectrometers provide multi-channel support for spectrometry. However, the seabreeze module defaults to a single channel with the normally supplied functions.
Andreas supplied example code for changing the channel using the f.raw_usb_bus.access functionality, but there is a timeout (well it just hangs, actually) issue when querying the devices for the number of modules/channels installed on the Jaz devices.
Good News: If you know your number of installed channels you can work around this and just directly send commands to set the channel.
Bad News: If you send the wrong command the device needs to be reset.
Weird News: If you work around the issue you must reset the channel you are polling from because the Jaz device Serial changes to each submodules.
steps to reproduce
import seabreeze
seabreeze.use('cseabreeze')
from seabreeze.spectrometers import list_devices, Spectrometer
import time
import struct
def init_seabreeze():
global devices
devices = []
for i in list_devices():
device_name = str(i)[-9:][:-1]
devices.append(device_name)
return devices
def get_channels(device):
spec = Spectrometer.from_serial_number(device)
spec.f.raw_usb_bus_access.raw_usb_write(data=struct.pack('<B', 0xC0), endpoint='primary_out')
data = spec.f.raw_usb_bus_access.raw_usb_read(endpoint='primary_in')
num_channels = struct.unpack('<B', data)
return num_channels
If you pass either device string from the list devices, the query will hang on spec.f.raw_usb_access.raw_usb_read(endpoint='primary_in')
work-around
To work around this issue, I have some code for selecting the device channel as per Andreas' e-mail, as well as a function to keep the USB device ID consistent by resetting the channel.
def get_spectra(device, channel):
spec = Spectrometer.from_serial_number(device)
spec.f.raw_usb_bus_access.raw_usb_write(data=struct.pack('<BB', 0xC1, channel), endpoint='primary_out')
time.sleep(.5) # Not necessary?
wavelengths = spec.wavelengths()
intensities = spec.intensities()
reset_channel(spec)
spec.close()
data = dict(zip(wavelengths, intensities))
return data
def reset_channel(spec):
channel = 0
spec.f.raw_usb_bus_access.raw_usb_write(data=struct.pack('<BB', 0xC1, channel), endpoint='primary_out')
Apologies if this is not super clear, this is my first issue/bug report/sharing of my own work-around.
Hi @evantaylor
Here's a few things you could try:
- use
'secondary_in'
or'secondary_in2'
as the endpoint argument for the read command - use the
pyseabreeze
backend
if none of the above work, I'll try to provide an example with the pyseabreeze backend that allows us to debug why it's not working
Cheers,
Andreas 😃