-
-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
High-speed acquisition mode using the Ocean Binary Protocol on OceanFX #59
Comments
Hi @aarpon I recommend you look for a datasheet of the OceanFX that has the full command set available. Best, |
Hi, great, thank you for the pointer! I will have a look. a2 |
Hi aarpon, |
Hi, nope, not yet. But I plan to work on it soon (hopefully from next week). Thanks, |
Hi, the python backend of python-seabreeze does not recognize the OceanFX spectrometer (0x2001). I have been (quickly) looking at the interfaces\defines.py file. Any pointers on how and where I can collect all the relevant information (dark pixels, end points, trigger modes)? Also, is there some documentation on how I can add a complete new spectrometer to pyseabreeze? Thanks, |
There is one small thing missing that I didn't wrap in the cseabreeze backend for version 1.0.0 😞 because it's only exposed via unformatted spectra... python-seabreeze/src/seabreeze/cseabreeze/c_seabreeze_wrapper.pyx Lines 809 to 815 in f0a08bb
There's two ways to do this:
With v1.0.0 I rewrote the whole pyseabreeze backend with v1.0.0 so that it's easier to extend: https://python-seabreeze.readthedocs.io/en/latest/contributing.html |
@aarpon I am using an Ocean FX-XR1. I am trying to add a new spectrometer using the documentation here Can you please provide me a copy of inputs for the following variables for Ocean FX?
|
@ap-- Unfortunately, I won't have access to the Ocean FX for the next few weeks... |
@aarpon Did you manage to implement the High-Speed Acquisition mode for Ocean FX on python-seabreeze? If yes, can you please share how you achieved it? |
@Roy4777 We ended up going down a completely different path (i.e. not using python-seabreeze). We should publish a paper about it soon, after which we will upload the code to either github or our gitlab instance. |
@aarpon That's awesome! I'll be looking forward to it. |
I have just got hold of an Ocean FX VIS-NIR for a pre-purchase test, which I will have access to for a couple of weeks. We want to use it to capture at high speed, and integrate it into a python code base. Just to clarify the current state of seabreeze at this time, it looks like seabreeze works with the FX, but it appears as a FlameX and doesn't support the short integration time and "throughput" or buffered mode of the FX required to reach the advertised 4500 spectra per second. Initially I thought a basic ctypes interface into the omnidriver.so/omnidriver.dll would be quick and easy, but no, it doesn't work. So I'm looking at other options. Writing my own wrapper around the Java or C++ omnidriver libraries would work, but be horribly tedious and bloated. Ultimately, I think it would be nice if I could hack at an open source library like seabreeze instead... Anyway, I have ssh access to the machine with the FX connected by USB, and will look at what it will take to implement the buffered acquisition mode. Any suggestions are welcome, and/or if you'd like me to test or report any data from the FX, let me know. Also, @aarpon if you have published that paper or have other hints about how you achieved fast acquisition from the FX, I'd love to hear it! |
Hi @ptapping Thanks for offering to contribute! ❤️ Implementing the fast buffer spectrum feature shouldn't take very long, as you have the hardware to test it. I don't have a developer data sheet for the OceanFX but since it uses the OceanBinaryProtocol for communication it should also be fairly standardized in its behavior. Still, if you find one it would be incredibly helpful. As described in an older comment of mine above https://github.com/ap--/python-seabreeze/issues/59#issuecomment-530549301 you do have two options to get started: Ultimately it just depends in which codebase you feel more at home. (1) is probably faster to do if you're familiar with c++ and cython and you just need it to work. (2) will probably be easier to iterate and hack on. I would probably recommend (2) and implementing it in the pyseabreeze backend. It's biggest problem is though, that it's quite a bit unpythonic, because I tried back then (bad decision) to make it mirror the abstraction layers of the c++ seabreeze library and over the years it became quite a bit ugly due to backwards-compatibility and hotfixes. But if I'll ever release python-seabreeze-v2 I would probably drop the cseabreeze backend and refactor pyseabreeze with only python3.6+ in mind... So let me know if I can do anything to get you started, and feel free to ask questions if you get stuck. If you open a draft PR, I can help you with code review and point you in the right directions. Cheers, |
Thanks for the encouragement! I managed to have a bit of a look at this today. So it turns out the Ocean FX detects as a FlameX using the cseabreeze API, and it reports that it supports the fastbuffer, databuffer etc features. So this is possible: import seabreeze
seabreeze.use('cseabreeze')
from seabreeze.spectrometers import Spectrometer
spec = Spectrometer.from_first_available()
spec.f.fast_buffer.set_buffering_enable(True)
spec.f.fast_buffer.set_consecutive_sample_count(100)
# The FlameX only supports 1000 us, the FX should support 10 us
spec.integration_time_micros(1000)
wavelengths = spec.wavelengths()
intensities = spec.intensities()
print(spec.f.databuffer.get_number_of_elements())
# Remember to do this...
spec.close() The databuffer reports the correct number of spectra acquired, but of course the call to So I'll start there and see how we go. If it works, then it should just need a new OceanFX device definition, which should be mostly a copy-paste from the FlameX one. Ultimately though, yes, I think it would be nice to implement the pyseabreeze backend. |
Hi, guys. As I said in a previous comment, we "solved" the issue in a different way. We contacted Ocean Optics and were sent a DLL (written in C# by Oliver Lischtschenko) that allows us to unlock the complete set of functionalities in OceanFX. For us, this solution was fair enough, since we are implementing a whole analysis platform, and were fine relying on having the bidirectional communication between the photometer and the CPU set up by someone else. As for our discussions with OO, the DLL can be freely used but must be distributed in binary form. We are somehow being delayed with our publications, but the idea is to get the whole code on github soon(ish). |
Thanks for the update! I haven't worked on this in a week or so, but made some progress. I started implementing the FX support into pyseabreeze, but got stuck pretty quickly on what looks like a low-level communications issue. I can open the spectrometer (which reads the serial number), but after that communications will time out and the spectrometer will stop responding. I did find that doing a low-level read would seem to clear buffers or something and the spectrometer would respond again. My guess is that a read and/or write in the OBP or transport layer is sending/receiving the wrong size data chunks or unexpected data. I found this issue #109 but not sure it's related. It might also be to do with the acknowledgement request flag. For example: import seabreeze.pyseabreeze as psb
api = psb.SeaBreezeAPI()
api.supported_models() # FX is listed
api.list_devices() # FX is detected
dev = api.list_devices()[0] # USB read timeout
dev = api.list_devices()[0] # Works this time...?
dev.serial_number # Got serial number OK
# But now everything will timeout again
# If we just read raw bytes, it will come back to life
_ = dev._transport._device.pyusb_device.read(0x01, 2**16)
# Sending raw commands like this seems to work every time
dev._transport.protocol.send(0x00000100, request_ack=False) # Request serial number
dev._transport.protocol.receive()
# But times out if the acknowledgement reply is requested?
dev._transport.protocol.send(0x00000100, request_ack=True)
dev._transport.protocol.receive() Anyway, have been busy with other tasks, so need to look into this more, but thought I'd report my progress. Any suggestions or ideas welcome of course. I've also attached the output of lsusb -v just in case it's of some use to anyone. |
I'd be happy to accept PRs for vendoring and integrating the DLL together with a python wrapper as another backend in python-seabreeze. It's too bad that it's win only.
The It's best to use The command acknowledging mechanism doesn't really make sense for USB connected spectrometers. The OPBProtocol is also used on spectrometers that support RS232... Let me know if that helps clearing things up, |
@aarpon Thank you. |
@sharmila-velamur I have to check with the original code by Oliver Lischtschenko: I think it could reach the maximum theoretical throughput; our solution saturates at around 2200 Hz, but in practice, for our purposes, we probably work at 800 Hz: to even get some signal from our fluorophores, we have to illuminate longer and therefore slow everything down. I am afraid for our code to be accessible online it will take some more time, but I can investigate whether we can share the original code from OO. As I mentioned in the past, it's C# and runs on Windows. I guess you could give mono a shot if you need to use it on other platforms and you (mostly) lose the UI. This code just gets spectra and plots them (a few times a second), but should have all the elements in place to get you started. |
Thank you so much for replying to me @aarpon. I do not need the UI at all. If I can get ~2000 Hz that would be pretty awesome (I am at 160 Hz now) to start with. What is mono? I have not come across that in the OceanFX documentation to the best of my recall. |
@sharmila-velamur. The code we got from Oliver Lischtschenko cannot be found anywhere officially, also I could never really find the documentation needed to replicate what it does. The problem is that Oliver's demo is heavily bound to a UI (it's just one big C# file). So, you'd need to extricate what you need from all the UI callbacks. Our tool is also a heavily graphical thing, and massively larger. Would you be able to work from a C# solution? |
Hi @sharmila-velamur and @aarpon Hope you all had a good start into 2021. It would be incredibly helpful, if one of you could get a USB Packet dump using https://desowin.org/usbpcap/ of OceanView (or alternatively in aapron's case: Oliver's tool) requesting a spectrum in high speed mode. I think I can reserve time this weekend to help test the code on your hardware and we could debug it together 😃 Let me know what you think or if I can be of further help in the meantime, |
Hi, @ap--. Happy new year to you, too! I should be able to get my hands on the hardware this week (can't tell you when, yet, though). And I can give it a shot. |
Hi @ap-- |
Cool! I should be able to get on the machine next week. I'll try to get a packet dump, too. |
Interesting! I assume this is closed source?
Awesome. I have to see when I can free up a day to work on this. Though, it is unlikely that I will find time in the next two weeks. So no rush. Have a great day 😃 |
I am not sure. I will find out tomorrow and let you know if this is a source I can share or not. Have a great one :) |
Hi all, I had been meaning to post here again with my progress, and the recent activity has reminded me about this... In the end, we did not end up purchasing the FX after our trial, so I didn't pursue this much further. We ended up choosing a more expensive option, but one which should hopefully also get us more spectra per second. Yes, Ocean Insight lost a customer because of their poor software and API. I still think the way to go is implementing the pure python OBP methods for the buffer management and retrieval of spectra. Add the FX in pyseabreeze/devices.py with a class something like this: class FX(SeaBreezeDevice):
model_name = "FX"
# communication config
transport = (USBTransport,)
usb_product_id = 0x2001
usb_endpoint_map = EndPointMap(
ep_out=0x01, lowspeed_in=0x81, highspeed_in=0x00, highspeed_in2=0x00
)
usb_protocol = OBPProtocol
# spectrometer config
dark_pixel_indices = DarkPixelIndices.from_ranges()
integration_time_min = 10
integration_time_max = 10000000
integration_time_base = 1
spectrum_num_pixel = 2068
spectrum_raw_length = (2068 * 2) + 64 # XXX: Metadata
spectrum_max_value = 65535
trigger_modes = TriggerMode.supported(
"OBP_NORMAL", "OBP_EDGE", "OBP_LEVEL", "DISABLED"
)
# features
feature_classes = (
sbf.spectrometer.SeaBreezeSpectrometerFeatureFX,
sbf.rawusb.SeaBreezeRawUSBBusAccessFeature,
sbf.nonlinearity.NonlinearityCoefficientsFeatureOBP,
) and to pyseabrease/features/spectrometer.py with something like: class SeaBreezeSpectrometerFeatureFX(SeaBreezeSpectrometerFeatureOBP):
def _get_spectrum_raw(self):
timeout = int(
self._integration_time_max * 1e-3
+ self.protocol.transport.default_timeout_ms
)
# the message type is different than the default defined in the protocol,
# requires addition of a new message type in protocol to work
datastring = self.protocol.query(0x00101000, timeout_ms=timeout)
return numpy.fromstring(datastring, dtype=numpy.uint8) (these are based off the HDX which is similar, but I'm not certain the spectrum_num_pixels is correct). However, the initialisation will still not work because of the issue I described above --- I think the initialisation and/or initial query of device serial number fails because the spectrometer does not return the expected number of bytes. I didn't follow this further to see exactly why, but setting the Good luck! |
@ap-- I have an Ocean FX XR1 in my lab. Are you still interested in developing the high frame rate support? If so, I could get you the packet dump/other info you need. We are very interested in my group to get this working with SeaBreeze. |
Hi @npeard Time is a bit scarce on my side, but I'd be very happy to offer assistance in implementing high-speed acquisition mode. I can sketch out the required functionality and maybe a savvy programmer from your group with more time can fill in the usb communication details? Cheers, |
A LabVIEW Solution: I had the same as problem as above obtaining high speed data from Ocean FX spectrometer using omnidriver. I decided to implement the known OBP protocol in Labview for controlling and reading data from the Ocean FX spectrometer directly via the USB port. I had written a small driver to replace the WinUSB driver with mine to read and write the USB port Labview Visa. Step 1. Replace the WinUSB driver with the OceanFX driver. Step 2 run the simple spectrometer VI to see if there is communication. The save high speed data into binary allows triggered high-speed acquisition from Ocean FX spectrometer. The analysis file provided will convert and graph the saved binary data. I was able to get around 4kHz data rate with Labview. Enjoy! |
@ap-- I used USBPcap to acquire the attached data with the Ocean FX XR1 running in 10us integration time (the minimum possible value, OceanView software acquires the spectra with net ~3800 fps). This is new for me, so I hope I did it correctly/got the necessary data. Any advice on how to proceed? |
Good morning @ap--, @tobiasium, @sharmila-velamur and @vchikan, and sorry for the long silence on this thread. As I mentioned earlier, we went down another path to exploit our OceanFX spectrometer for high-content screening. Since the first paper is now accepted and in print, I can finally share the code with you: https://github.com/SpectraSorter/SpectraSorter. Again, while our code (in C#) is free and opensource, we make use of a closed-source DLL by Oliver Lischtschenko from OO (https://github.com/SpectraSorter/SpectraSorter/blob/master/src/SpectraSorter/OBP_Library.dll) that implements the Ocean Binary Protocol and allows us to reach full performance at 4,500 spectra collected per second. I don't know if you can take advantage in any way from either the source code, the OBP library or, hopefully!, SpectraSorter itself, but we would definitely be interested in knowing if it can work out of the box with your hardware (we could only test it with our OceanFX). You can find the user manual at https://github.com/SpectraSorter/SpectraSorter/blob/master/docs/SpectraSorter_User_Manual.docx and a short video demonstration at https://vimeo.com/601011694. Any feedback is greatly welcome! Thanks in advance, |
Hi @aarpon, @npeard You can then check the transferred data. For the command in the screenshot it boils down to:
Which you can check against the datasheet for the OceanFX that's linked to in a response further up. Ultimately you just need to send the commands in the correct order. The package dump can help you with that. (If you check yours, it turns out you're missing the setup commands, and it just captured very many of the GetRawSpectrumWithMetadata commands) Cheers, |
Hi, @ap-- Thanks, it would be great if you could add a reference to SpectraSorter to the python-seabreeze docs! |
Hi @aarpon Thanks a lot for the contribution of Spectra Sorter, I am trying to use the software to apply one of the triggering functions of OCEAN FX, but unfortunately I don't have the "Arduino MEGA 2560", I am using "Arduino MEGA ADK". Do you know if it is possible to modify the source code to adapt the software for the Arduino that I have?, if yes could you give some insight where I should change the code for my specific arduino?. Cheers, |
Hi, @italavica. The communication with the Arduino board is managed by the |
Hi @aarpon, |
Hi, @italavica. Sorry, yep. Forgot to mention that ;-) |
Hi, @aarpon. As I mentioned, I managed to connect the arduino "MEGA ADK" and set the parameters through the software (Spectra Sorter), but once I start the acquisition using the triggering mode "Legacy Synchronous" it doesn't display and save the spectrum in the csv file. What do you think it can be the issue? Thanks in advance. Cheers, |
Hi, @italavica. I am afraid that this trigger mode is not implemented. |
Hi, @aarpon, I am just wandering if you already implemented the "Legacy Synchronous" triggering mode?, if not could you advice me where to start for implement it? |
Hi everyone. I'm in the process of implementing the fast buffer method for the cseabreeze backend at least and I could use some input. As mentioned before the spectra come as raw spectra and have a 64 byte header each. So this is the code I came up with: I get back spectrums that are the "same" as when read directly with A few thoughts:
I have full access to an OceanFX-XR1 spectrometer, so I'll probably be able to put some more effort into this. I might even start implementing it in the pyseabreeze backend but wanted to get something to work quickly so I went this route. |
Here's a dump of the bytes received for 3 spectra in case anyone wants to have a look. I have shone my iPhones LED into the detector to make the spectra distinguishable. |
@padalev great to see that there's some new momentum regarding the OceanFX support. (1) The metadata structure should be as follows: (2) some more information regarding the fast spectrum functionality
(3) here's the link to the limit: Line 53 in 0be9fcb
|
Trying to stay compatible with the original c++ library was in hindsight a big mistake. Ocean Insight does not seem to support the open-sourced seabreeze library anymore, and there have been no updates from them for years. At the time I wrote this python library, I designed pyseabreeze to be as close as possible to the c++ interface so that I would be able to easily port new functionality to the pure python implementation when it would have been added by ocean optics. This just made pyseabreeze a lot more complex compared to when I would have written it as a Python first library. the So to summarize, that's been a long explanation to just say: don't worry about the compatibility between them. structuring the metadata as a dict or namedtuple makes a lot of sense. |
wow. That's exactly what I was looking for. I have already started implementing that to return a list of
that is very helpful! I wasn't quite aware of the exact mechanism.
I see. Why is the file called FlameX...? Is that an internal ocean insight name for the model? Or is that a group of spectrometers? I'm afraid I will affect other spectrometers by just changing that value...
I already had a feeling. Sad to see companies dropping the open source approach. Seems like we are doing their job now...
all the more reasons to implement the fast Buffer functionality to that backend as well I guess. I have working code now but I want to improve error handling a bit and add the new functionality to the docs. Then I will go for the pull request, since it is a general function, which does not theoretically depend on the specific spectrometer. I'll do the rest of the compatibility separately afterwards. There remains one issue that I see right now: |
|
spectrometer and system information
current problem
Using the Ocean Binary Protocol (OBP) it should be possible to achieve a rate of 4500 spectra/s over USB. This requires the following sequence of operations (pseudocode from the OBP documentation for the OceanFX spectrometer):
Is there an API that already provides this buffered reading of spectra? If not, could you provide me with some hints on how to implement it? In particular, I would like to know if it is possible to perform the
Set buffering = enabled
andSet number of back-to-back spectra per trigger = 50000
using python-seabreeze with any of the backends, and how.The text was updated successfully, but these errors were encountered: