The timing between turning laser on and stimulus on

Hi Taylor,

We just zoomed with Karim and he confirmed that the problem shouldn’t be the laser.

I’m skeptical, but we can do some tests to find out.

I’ve attached a MATLAB function (timeLaserConfig) that measures the time it takes to configure all four channels of the laser. Each channel is set to operate in sinusoidal mode with a frequency of 0.5Hz at 50% gain. The test uses MATLAB’s timeit function to send this configuration repeatedly and report the median time. To run the test, call the function with the serial port as the only argument, e.g.

timeLaserConfig /dev/cu.usbmodem23301

(FYI, the first run is sometimes slower than subsequent runs, so I recommend running it a few times.)

To determine the source of the latency in laser configuration, I suggest doing the following tests:

  1. Run timeLaserConfig on the Mac to which you normally connect the laser.

    If, over a couple runs, you get a median time that is much less than 60ms, then the issue must be with MWorks.

    If you get times of ~60ms or more, then clearly the issue is not with MWorks, since this test does not involve MWorks in any way. In this case, move on to test #2.

  2. Connect the laser to a non-Mac (i.e. Windows or Linux) system, and run timeLaserConfig there. You may need to use MATLAB’s serialportlist function to determine the name of the serial port.

    If, over a couple runs, you get a median time that is much less than 60ms, then the issue must be with macOS.

    If you get times of ~60ms or more, then the issue is independent of the operating system, meaning it must be due to the laser itself.

    If you don’t have access to a non-Mac system on which to perform this test, you could ask Karim to try it. This wouldn’t be ideal, though, because he may not have a device that’s exactly identical to yours. (In particular, the firmware may be different.)

For reference, I tested timeLaserConfig with an Arduino board running my QCUALOR simulator firmware. The simulator just receives commands over the serial port, validates them, and sends them back. In other words, it does all the serial I/O that the real device does and nothing more. After the first run, the test consistently returned a median time of about 5ms. (The equivalent test using MWorks returns a median time of about 0.8ms. MATLAB itself apparently adds a fair amount of latency, but it’s still a lot less than 60ms.)

Cheers,
Chris
timeLaserConfig.m (562 Bytes)

Hi Chris,

I tried the timeLaserConfig and it kept giving this error of connection error. I’ve attached a screenshot of the error below. I tried both running the script during and after the protocol and neither worked. Would appreciate if you could take a quick look! Thank you.

Best,
Taylor

Your MWorks experiment can’t be open, otherwise MWorks and MATLAB are going to interfere with each other. I recommend closing MWServer before you run timeLaserConfig.

Chris

Hi Chris,

We were able to do this testing on both a Mac and a PC. Both had a delay of ~60ms. Then I think we can rule out MWork or MacOS causing the delay. We are waiting for Karim’s response but thank you again for helping us troubleshooting.

Best,
Taylor

Hi Chris -

We passed your Matlab test to Karim (Laser developer) - and he thought there might be a better way to measure serial communication time. He ended up measuring the delays on his end - and found them to be close to 10-19 ms. His intuition is that the delays in “execution time” that we’re measuring might be related to the operating system?

To loop you in, I’ll copy some of his thoughts below - taken from various emails:

Message 1 from Karim:

I looked at Chris’ MATLAB code, to my understanding it sends four configurations then measure the time to echo response, so basically it measures the time of an echo received after 16 bytes, correct?. I’m not sure if this is a good measure of the modulator response time. To measure the time response I suggest the following steps:

  • Set a digital output pin that goes high right before sending the command (only single command to be sent: 4 bytes).
  • Immediately follow by turning the gate high and observe the optical output on an oscilloscope.

Using time measurement feature in the oscilloscope, measure the time difference between the digital output pin and optical output, this is a good measure of response time.

Message 2 from Karim:

I built a special hardware/software setup to measure the serial communication response for the laser modulator, after many tests (10-20 runs) the response time measured was between 11 ms and 19 ms only.

Response time here is defined as the time between sending a serial command and the laser modulator generating an optical output.

Chris’s MATLAB script doesn’t measure the response time, rather the execution time of the “write to serial port” function. Such measure is operating system dependent and inaccurate in the case of the laser modulator.

Message 3 from Karim:

I’m not sure if Chris can change the execution time because it is also connected to the implementation of the “write to serial port” function in software. Such function is implemented differently in every programming/scripting language, add to that the OS dependency I mentioned, developers don’t have much control on the execution time.

For the test setup, I have used C++ language which is known for its fast execution compared to most programming languages.

Does any of this new info suggest that we might be able to optimize the MWorks laser to get the delay a bit shorter? I think MWorks uses some C++ expressions so maybe there’s a way forward?

Many thanks!

Yasmine

Hi Yasmine,

Does any of this new info suggest that we might be able to optimize the MWorks laser to get the delay a bit shorter?

No.

He says he looked at my code. Did he ever try running it? It sounds like he didn’t, and he answered a different question entirely:

Response time here is defined as the time between sending a serial command and the laser modulator generating an optical output.

You weren’t asking about how long it takes the laser to generate an optical output. You were asking: Why does it take ~60ms for the laser to receive commands, configure itself, and return a response?

He also said:

Set a digital output pin that goes high right before sending the command (only single command to be sent: 4 bytes).

Of course sending a single command and receiving the response will take less time than sending four commands (as my MATLAB test does). Try it yourself: In timeLaserConfig.m, comment out three of the sendConfig calls, and run the test. My guess is that it will take about a quarter of the time (~15ms).

As for this comment:

Such measure is operating system dependent and inaccurate in the case of the laser modulator.

Sure, serial I/O timing may be operating-system dependent. But you ran my test on two different operating systems (macOS and Windows) and got consistent results. That doesn’t suggest operating-system dependence to me.

Can I suggest that Karim

  1. actually runs my test on his hardware and shares the results with you, and
  2. modifies his alternative timing test to configure and activate all four laser channels (instead of just one)?

As for this:

For the test setup, I have used C++ language which is known for its fast execution compared to most programming languages.

MWorks is also written in C++. This includes all of the code that does serial I/O with the laser.

Chris

Hi Chris -

You are correct. Karim doesn’t use/have Matlab.

I’ll push him to do the tests you suggested.

Best,
Yasmine

Hi Yasmine,

You are correct. Karim doesn’t use/have Matlab.

I can easily write a Python version of the test for him, if he can run that.

Also, are you sure it’s really worth your time to pursue this further? As we’ve discussed, even if it does take ~60ms to configure the laser, you should be able to move the configuration to a point in your experiment where it doesn’t matter. The actual activation of the laser happens when you set the laser gate TTL high, and that should have very low latency (<1ms). Just a thought.

Chris

Hi Chris -

Thanks for elaborating.

Agreed. Based on recent measurements we’ve made, setting the laser gate high takes about 1-2ms (not more).

Forwarding just one final message from Karim.

I thought you wanted to know the time between sending the command to the modulator and generating an optical output. Chris wants to measure the time between sending a command and receiving an echo after configuring all four channels, which is a different question, that would have saved me the hustle of building a hardware setup!!. However, the answer is the same, and here is the explanation:

The tests were done on a single channel since I have only one laser diode attached to the testbench version of the modulator I have in the lab. The 11-19 ms is the time for a command to be sent, echo received, modulator configured and gate is activated.

Since a command configures a single channel, so repeating the same process 4 times to configure all channels will take close to 4x the response time I measured, this is the 60 ms you and Chris measured, which seem normal and reasonable. No need for me to run the MATLAB code.

Now that I finally understand that the ~60 ms delay is related to the configuration of ALL 4 channels together - I’d like to ask:

Since 90% of our protocols involve variations in only 1 channel of light, is it possible to only configure 1 channel (or alternatively only the relevant subset of channels) thereby reducing the ~60ms delay futher? Or is this not a practical solution and we should focus on where in a protocol we configure the laser?

Thanks for all your help!
Yasmine

Hi Yasmine,

Since 90% of our protocols involve variations in only 1 channel of light, is it possible to only configure 1 channel (or alternatively only the relevant subset of channels) thereby reducing the ~60ms delay further?

Yes, that’s certainly possible. I’ll have to modify the QCUALOR plugin, but it’s not a big change.

When initially developing the laser interface, I believe my thinking was that it would be simpler and safer to always explicitly configure all four channels when starting and stopping the device, including explicitly configuring channels in “off” mode to be off. But MWorks could do the following instead:

  • When the experiment loads, explicitly set all channels to “off”.
  • When start_io_device is called, configure only channels with modes other than “off”.
  • When stop_io_device is called, turn off only the channels that were configured in start_io_device.

The only downside is that laser configuration will take a variable amount of time, depending on the number of channels you want to turn on.

How does that sound?

Chris

Hi Chris -

Sorry for the delay!

Taylor and I finally had a chance to chat about this!

We really like your suggested changes - and Taylor suggested a minor modification related to the laser hardware. In practice, since channels 1&2 share a single optical fiber output (as do channels 3&4) we really only need to configure a max of two channels at any one time for 99% of our experiments! So we could just configure 2 channels at a time (channels 1&2 OR channels 3&4) and that way the configuration time will always be ~30ms across 99% of our MWorks protocols.

For the 1% of future experiments, we would like the flexibility of configuring all 4 channels (if possible) - bringing us back up to 60ms, and we would figure out ideal places in the protocol for the laser to be configured.

Thoughts on this possibility?

Cheers,
Yasmine

Hi Yasmine,

Your proposal makes sense and seems like a good compromise. Just to be completely clear, MWorks will do the following:

  • When the experiment loads, explicitly set all channels to “off”.

  • When start_io_device is called, if either of channel 1 or channel 2 has a mode other than “off”, configure both channel 1 and channel 2 (one of which may be configured to be off). Likewise, if either of channel 3 or channel 4 has a mode other than “off”, configure both channel 3 and channel 4.

  • When stop_io_device is called, turn off only the channels that were configured in start_io_device. This could be just channels 1 & 2, just channels 3 & 4, or all four channels.

Does that sound right? If so, I will try to get this change in to the nightly within the next few days.

Thanks,
Chris

Hi Chris,

We will think more about whether to configure each channel individually or two channels that share a single optical fiber together. We will discuss further before you invest your time and we will reach back as soon as we have an idea.

In the meantime, I have one more related question. For some protocols, the laser has the same configuration (same amplitude, same output channel, etc.) throughout the task. The only modulation we need throughout these kinds of protocols is turning the laser on and off. Therefore, is it possible for us to configure the laser only once at the beginning and stop it at the end of the protocol (i.e. start_io_device(laser)at the very beginning of the protocol and stop_io_device(laser) at the very end)? Then for the laser trials, we only do turn_laser_on without worrying about start_io_device(laser).

I tried it with one of our protocols. It didn’t seem to drive the laser at all but just want to double check if that is even possible. Thank you!

Best,
Taylor

Hi Taylor,

For some protocols, the laser has the same configuration (same amplitude, same output channel, etc.) throughout the task. The only modulation we need throughout these kinds of protocols is turning the laser on and off. Therefore, is it possible for us to configure the laser only once at the beginning and stop it at the end of the protocol (i.e. start_io_device(laser)at the very beginning of the protocol and stop_io_device(laser) at the very end)? Then for the laser trials, we only do turn_laser_on without worrying about start_io_device(laser).

Yes, this should work. Once the laser is configured with start_io_device, it will retain that configuration until you call stop_io_device or call start_io_device again. To turn it on and off without changing the configuration, just set vpixx_dout_laser_gate to true or false, respectively. At least, that’s my understanding of how the laser is supposed to work. (Note that, if you haven’t already, you will need to remove the start_io_device and stop_io_device calls from the actions attached to variable laser_turning_on.)

I tried it with one of our protocols. It didn’t seem to drive the laser at all

That’s strange. Like I said, my understanding is that the laser should work as I described, but I could be wrong. Or maybe you accidentally called stop_io_device somewhere?

Chris

Hi Chris,

I tried again and for some reason, it activated the laser only when the very first trial was a laser trial but the laser was not turned on for any other following laser trials. I will try to see if I can make it work but this is low priority. We will keep the way we configure and start laser, which works for our current protocols.

In terms of the new idea for configuring the laser channels, we discussed further and decided that configuring each channel individually is a good idea. We decided that it might be ok for the configuration time to be a variable since the configuration time and the number of channels to be configured is about linear (~15ms for configuring one channel). Thank you for helping us implementing this!

Best,
Taylor

Hi Taylor,

In terms of the new idea for configuring the laser channels, we discussed further and decided that configuring each channel individually is a good idea.

OK, I will get that change in to the nightly build soon.

Thanks,
Chris

Hi Taylor,

The QCUALOR changes we discussed are now in the MWorks nightly build. Just to recap how things now work:

  • When the experiment loads, all channels are configured to “off”.

  • When start_io_device is called, only channels with non-“off” modes and channels going from a non-“off” mode to “off” are configured. No configuration commands are sent for channels with mode “off” that are already off.

  • When stop_io_device is called, all channels that are currently in non-“off” modes are configured to “off”. No configuration commands are sent for channels with mode “off” that are already off.

As was previously the case, it’s OK to invoke start_io_device without invoking stop_io_device first. However, regardless of whether you call stop_io_device or not, if the MEG line is high when start_io_device executes, you still need to set it low and then back to high in order for the configuration change to take effect.

Also, I added a new parameter: log_commands. If set to true, MWorks will print to the MWServer console the serial commands sent to and received from the device. This could be useful if you (or Karim) want to know exactly when and what data is being exchanged between MWorks and the device. (It was also very helpful to me when testing these changes.)

When you have a chance, please give the new build a try, and let me know if you run in to any issues.

Cheers,
Chris

Hi Chris,

Sorry for the delay but we were doing some testings with the new nightly build. The configuration time was definitely shorter but it was still a variable ranging from 2ms to 20ms. We are trying to figure out why and whether we should expect this from the laser. We will do more testings and get back to you as soon as we have an answer. Thank you!

Best,
Taylor

Hi Taylor,

The configuration time was definitely shorter but it was still a variable ranging from 2ms to 20ms. We are trying to figure out why and whether we should expect this from the laser.

The new log_commands parameter might be helpful, as it will let you confirm that configuration commands are being sent when you expect. You should see one pair of SEND and RECV messages for each channel being configured.

FYI, I’m going to be out on vacation all of next week, so I won’t be able to help much until I’m back the following week.

Cheers,
Chris

A post was split to a new topic: Some questions