Issue saving high res buffer with Oscilloscope

Moku model: Moku:Pro
Operating system: macOS 12.6
Software version: 2.4.2
Firmware version: 569
Python Moku API version: 2.4

Bug or support request description:

Hi there,

I’m working the Python Moku API to set up a script to take and save data at various settings for a device, but am running into an issue with saving the high resolution data buffer. It seems that it works the first time, but subsequent tries raise an error:

MokuException: ['Error occurred while saving high resolution data frame']

The error seems to go away if I completely restart the Moku and then rerun the Python code (taking over control again). However, the same error returns after subsequent tries. Is this a known issue with the using the Oscilloscope instrument via the Python API? I’ve also noticed that the same line can sometimes return a timeout error.

Code:

from moku.instruments import Oscilloscope
import matplotlib.pyplot as plt
import os
import time
from datetime import datetime

import contextlib

@contextlib.contextmanager
def connect_instrum(MokuInstrument, ip_address, force_connect=False):

    MI = MokuInstrument(ip_address, force_connect=force_connect)
    try:
        yield MI
    except Exception as e:
        raise e
    finally:
        MI.relinquish_ownership()

moku_ip = '192.168.73.1'

with connect_instrum(Oscilloscope, moku_ip, force_connect=True) as i:
    i.set_defaults()

    # Trigger on input Channel 1, rising edge, 0V 
    i.set_trigger(
        type='Edge',
        source='Output1',
        level=0,
    )

    # View +-5usec, i.e. trigger in the centre
    i.set_timebase(-0.1, 0.1)

    # Generate an output square wave on Channel 1, 1Vpp, 1kHz, 0V offset
    i.generate_waveform(1, 'Square', amplitude=1, frequency=1e3, duty=50)
    # Set the data source of Channel 1 to the generated output sinewave
    i.set_source(1, 'Output1')

    # Set the data source of Channel 2 to be Input 1
    i.set_source(2, 'Input2')

    plt.grid(b=True)
    plt.ylim([-1, 1])

    line1, = plt.plot([])
    line2, = plt.plot([])

    # Configure labels for axes
    ax = plt.gca()

    time.sleep(3)
    data = i.get_data()
    plt.xlim([data['time'][0], data['time'][-1]])

    # Update the plot
    line1.set_ydata(data['ch1'])
    line2.set_ydata(data['ch2'])
    line1.set_xdata(data['time'])
    line2.set_xdata(data['time'])
    print(i.summary())
    
    response = i.save_high_res_buffer(comments="Test")
    file_name = response["file_name"]
    i.download(
        "ssd",
        file_name,
        os.path.abspath(f'./test{datetime.now().strftime("%Y%m%d_%H%M%S")}.li'),
    )

Error:

---------------------------------------------------------------------------
MokuException                             Traceback (most recent call last)
<ipython-input-14-952d6b0ded09> in <module>
     49 
---> 50     response = i.save_high_res_buffer(comments="Test")
     51     file_name = response["file_name"]
     52     i.download(

/opt/anaconda3/lib/python3.8/site-packages/moku/instruments/_oscilloscope.py in save_high_res_buffer(self, comments)
    487             comments=comments,
    488         )
--> 489         return self.session.post(self.operation_group, operation, params)
    490 
    491     def get_samplerate(self):

/opt/anaconda3/lib/python3.8/site-packages/moku/session.py in func_wrapper(self, *args, **kwargs)
     12     def func_wrapper(self, *args, **kwargs):
     13         response = func(self, *args, **kwargs)
---> 14         return self.resolve(response)
     15 
     16     return func_wrapper

/opt/anaconda3/lib/python3.8/site-packages/moku/session.py in resolve(self, response)
    148                     return data.data
    149                 elif data.success is False:
--> 150                     self.handle_error(data.code, data.messages)
    151             else:
    152                 self.handle_http_error(response)

/opt/anaconda3/lib/python3.8/site-packages/moku/session.py in handle_error(code, messages)
    112             raise exceptions.UnexpectedChangeError(messages)
    113         else:
--> 114             raise exceptions.MokuException(messages)
    115 
    116     @staticmethod

MokuException: ['Error occurred while saving high resolution data frame']
1 Like

Looking around the forum a little bit, this could be a related issue to this one from about 8 months ago:

Have there been any updates on that issue? For now we will use the datalogger to take continuous data and trigger offline.

I was able to reproduce this issue on my end with the ‘Error occured while saving high resolution data frame’ message appearing. It seems like the easy fix is to remove the comments=‘Test’ for now, however I have submitted this as a bug to our software team. Thank you for pointing this out to us and let me know if this fixes the issue for you!

Hi @Sam.Speece,

Unfortunately, I still seem to get the error after removing that comment - I tried restarting the Moku and using it with a different device (the Mac app), but still have one successful data taking with the oscilloscope, before the subsequent runs raise the same error.

FYI, I’ve essentially taken the code I used from the API examples:

When you removed that comment, you could re-run the script over and over again to collect new data?

Quick update on some of the testing I’ve done and what I’ve found has worked.

I removed majority of the matplotlib lines to get minimum viable code that reproduces the issue and added back in the comments=‘Test’ bit too. It seems there is one line that causes the high res data download issue to appear infrequently (about 3 of every 5 runs ends in high res download error). I think I just got lucky previously when removing the comments=‘Test’ part and got it to run 3 times in a row without error.

In your original code, removing line 53 (calling get_data()) seems to resolve issues for me and I’ve gotten it to run successfully 10 consecutive times. There is likely some strange interaction with using both get_data() and save_high_res_data() in the same script that is causing issues.

Alternatively, if you still need to call get_data(), I have found that calling it after I call save_high_res_data() does not produce any errors.

Let me know if this one helps you any better.

Thanks for the update! I tried doing the same thing, and it definitely improved the success rate, but I still do get the same MokuException errors every couple of runs. One other thing that I was wondering could be part of success/failure rate it is how I’m connecting to the Moku. Right now, I’m connecting via WiFi. Are you using the same connection method?

I played around more with commenting out various lines and seeing what combination of lines raises the error. In my experience, it seems like the error was only raised in the scenario that both:

  1. I am generating some type of waveform through an output
  2. I am triggering on that output

If both were not true, then I didn’t get an error over 10 runs. If both were true, then I got, e.g., 6-8 errors out of 10 runs. In other words, in the code I’m using, if I set the trigger source to "Input2", there’s no error, but I have about a >50% chance of an error with the source set to "Output1".

Here’s the simplified code I’m using, which should be about the same as you described:

from moku.instruments import Oscilloscope
import os
import time
from datetime import datetime

import contextlib

@contextlib.contextmanager
def connect_instrum(MokuInstrument, ip_address, force_connect=False):

    MI = MokuInstrument(ip_address, force_connect=force_connect)
    try:
        yield MI
    except Exception as e:
        raise e
    finally:
        MI.relinquish_ownership()

moku_ip = '192.168.73.1'

with connect_instrum(Oscilloscope, moku_ip, force_connect=True) as i:
    i.set_defaults()

    i.set_trigger(
        type='Edge',
        source='Output1',
        level=0,
    )
    i.disable_input(3)
    i.disable_input(4)

    i.set_timebase(-0.1, 0.1)

    i.generate_waveform(1, 'Square', amplitude=1, frequency=1e3, duty=50)
    i.set_source(1, 'Output1')
    i.set_source(2, 'Input2')


    time.sleep(3) # wait for Moku to finish setting channels
    
    response = i.save_high_res_buffer()
    file_name = response["file_name"]
    i.download(
        "ssd",
        file_name,
        os.path.abspath(f'./test{datetime.now().strftime("%Y%m%d_%H%M%S")}.li'),
    )

I just wanted to give you an update from our API dev team that this issue has been partially fixed as of our latest update 2.5.1 (17690) and no longer requires restarting your Moku:Go. We are still investigating why the error is thrown every now and then and I will update this thread once I have more information. Thank you for your patience!

Hi. I’m using Moku:Pro with this version (2.5.1 build 17690) and have the same issue when saving hi-res data - the device stops communicating with the desktop app until I do a hard reset. Can this fix be extended to the MP?

1 Like

Moku model: Moku:GO
Operating system: Windows 11
Hardware Version 4.0 Moku:Go
Firmware version: 601
Liquid Instruments Moku LabVIEW VI package Version: 3.3.2.1

Bug or support request description:
I seem to be having a similar problem as described in the original post but on a Moku GO. I setting up the oscope for a long acquisition ~30secs.
If I try saving the high resolution buffer after calling the VI that use API oscilloscope/get_data and confirming all the samples are available, I get the error message in the original post: “Error 41 occurred at Moku OSC save_high_res_buffer.vi - UNEXPECTED_ERROR: Error occurred while saving high resolution data frame” after calling the VI with save_high_res_buffer call.
If I skip get_data read, and just try save_high_res_buffer, the I get a timeout error in 10 secs or so even though I set the timeout to 60 secs.
Is it possible this bug still exists.

Hi @bbean ,
Thank you for reaching out! The bug that was affecting save_high_res_buffer() has been fixed, but I suspect this is a bug with the timeout parameter. The problem seems to be that the high res buffer is getting saved before enough data is collected (i.e. 30 second timebase but only 15 seconds worth of data). The timeout parameter should accommodate this, but the workaround is adding a sleep or pause of >30 seconds before calling save_high_res_buffer(). I hope this helps!

I’ve discovered a few things:

  1. The save_high_res_buffer LabVIEW VI was timing out (error 56) on the Rest Client HTTP Post because the POST VI internal timeout defaults to 10secs (not enough time to capture a 30sec sweep). Unfortunately, I can’t attach a new VI I made to fix save_high_res_buffer.vi. But the new fixed VI checks the api input ‘timeout’ and if it is longer than the default or current REST Client timeout, it chooses the higher timeout value. This fixes the issue with the LabVIEW timeout error (Error 56).
  2. If I don’t’ set the Wait Until Complete flag true in the get_data call, the save_high_res_buffer will have an error "UNEXPECTED_ERROR: Error occurred while saving high resolution data frame” (error 42) even if I wait for enough samples to arrive from get_data before calling save_high_res_buffer. Unless I’m doing something wrong, this is annoying bc the user won’t be able to see a real-time plot (like the Moku App) when waiting for long traces.
  3. The save_high_res_buffer api call seems to take an additional sweep of the data. For instance, if my timebase setup for the oscope totals 12 secs, the call to get_data will take ~>12secs (1 sweep) and the save_high_res_buffer will take an additional 12 secs (seemingly indicating its retrieving a second sweep). Not sure how I will be able to grab the high res buffer for the sweep i want (only the first one) without a single sweep mode in the API.

-Brian

Hello @bbean ,
The problem seems to be that you are using both get_data() and save_high_res_buffer(). Although this isn’t an issue in itself, the data that is collected in each call is going to be different. When you call get_data(), the Moku will collect data over the timespan, and send it to the PC. Then, save_high_res_buffer() is called, which will again collect data over the timespan. I would recommend to wait until all of your data has been collected, and then use save_high_res_bufer() to collect, visualize and process the data. I hope this was helpful!

Hello @Dylan ,
Thanks for your quick response and feedback. That is helpful
What I’d really like to be able to do, is automate the entire processes that our scientists use in the Moku app with the API and it sounds like that may not be fully possible at the moment.
What our scientist do in the Moku App:

  1. Setup the Moku Go Oscilliscope to capture a single 30 sec pulse
  2. Monitor and observe a single trace in the Moku App while its being collected (to see its progress) and full resolution saved
  3. Hit the export data button at the top center of the Oscilliscope App
  4. Export the full resolution data to an li, csv or etc to a named file
  5. Download the file and post process it.

From what you are describing and my quick review of the API, Automating 1 seems possible at the moment (with a work-around for the Single option that you mentioned in another thread). But 2,3 and 4 are not possible.
Based on your last reply it sounds like when using the API, I will just have to display a message for 30 secs to the user that the program is waiting for the data.
Its disappointing that 1-4 can’t be fully recreated with the API.