Closed HaoyangRong closed 7 years ago
Thanks for the report! The main problem was that this function had a type instability. It produces the conversion function that gets executed on every sample, so it caused a major slowdown. After fixing that I get a 10x improvement in speed.
I also realized that for digital signals we were doing two more mapping steps than necessary because the raw units (UInt8 true/false) are the same units as the vector that you're feeding in. After fixing that I got another 2x, for a total of 20x speed increase. Let me know how that works for you. If it's not fast enough there is still more that we can do.
See PR #31
With sample_rate=50000s^-1, n_blck=2, n_stimID=6
the original version took \~90s to append all stimuli, but it took only \~7s after your update. I noticed a significant increase in speed!
When it comes to writing stimulus profile for a real experiment n_blck
ranges from 4 to 6 and n_stimID
\~=15, it took about 35s or more. Considering the full waveform file would include up to 5 additional channels for dual-color imaging (piezo, 2 cameras, 2 lasers), I hope the speed can be further increased if possible. The stimulus waveforms are pretty sparse, e.g. they only have a small portion of true
s here and there. Maybe that's something to be utilized?
I'm looking into the generation of other control commands. I'll keep you updated.
So my thought was that as a next step we can create a version of append!
that accepts vectors that are already compressed, i.e. instances of RLEVector
. That means it would be the responsibility of the user to do the compression beforehand. I don't think this would complicate things much for the user. An RLEVector
is just a vector with elements that are RepeatedValue
s Here's an example of how you could construct a stim on, stim off sequence:
nsamps_on = 100
nsamps_off = 200
stim_vec = ImagineInterface.RepeatedValue{Bool}[]
stim_on = ImagineInterface.RepeatedValue(nsamps_on, true)
stim_off = ImagineInterface.RepeatedValue(nsamps_off, false)
push!(stim_vec, stim_on)
push!(stim_vec, stim_off)
#currently this isn't implemented, but I will add it
#(assume stim_com1 is an ImagineSignal for a stimulus command)
append!(stim_com1, "on_off", stim_vec)
This will be much faster because it doesn't require iterating through the sample vector for compression. Now I will work on a PR that implements the above version of append!
and also exports the RepeatedValue
and RLEVector
types so that you don't have to type ImagineInterface.
to use them.
Note that this works for digital signals, but it's less useful for analog signals like the piezo that are almost always changing. But since the piezo signal is usually repeated every stack it should not cause a performance problem as long as you append one stack and then duplicate it.
So this is done, see #32
Here's an updated example script:
using ImagineInterface, Unitful
import Unitful:s
ocpi2 = rigtemplate("ocpi-2"; sample_rate = 50000s^-1)
stim_com1 = getstimuli(ocpi2)[1]
nsamps_on = 100000
nsamps_off = 200000
stim_vec = RepeatedValue{rawtype(stim_com1)}[]
stim_on = RepeatedValue(nsamps_on, true)
stim_off = RepeatedValue(nsamps_off, false)
push!(stim_vec, stim_on)
push!(stim_vec, stim_off)
append!(stim_com1, "on_off", stim_vec)
Using this approach stimuli signals can be generated instantly. I still recommend that for camera and piezo commands you reuse the signal for a single stack instead of doing it this way
That's awesome! I'll try it out.
The change resulted in a huge improvement in speed! Thanks!
Glad it helped!
On Wed, Aug 16, 2017 at 1:42 PM, HaoyangRong notifications@github.com wrote:
Closed #30 https://github.com/HolyLab/ImagineInterface/issues/30.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/HolyLab/ImagineInterface/issues/30#event-1208851006, or mute the thread https://github.com/notifications/unsubscribe-auth/AE78hJm_MYERnTKq-ArusyWENPOlFIXFks5sYzgXgaJpZM4OqZqn .
My complete stimulus sequences consists of individual pre-defined sequences arranged in an order. Sometimes, such an individual sequence can have a zero length, since its corresponding time length might be 0 due to the protocol.
append!
has trouble working with zero-length sequence, and it seems to be sequence value dependent.
Running code:
using ImagineInterface, Unitful
import Unitful:s
ocpi3 = rigtemplate("ocpi-2"; sample_rate = 5s^-1)
stim_com1 = getstimuli(ocpi3)[1]
nsamps_on = 10
nsamps_off = 20
stim_vec = RepeatedValue{rawtype(stim_com1)}[]
stim_on = RepeatedValue(nsamps_on, true)
stim_off = RepeatedValue(nsamps_off, false)
stim_0=RepeatedValue(0, false)
push!(stim_vec, stim_on)
push!(stim_vec,stim_0)
push!(stim_vec, stim_off)
append!(stim_com1, "on_off", stim_vec)
using Plots, ImaginePlots
plot(ocpi3)
I got , which looks pretty good.
If I switch push!(stim_vec, stim_on)
and push!(stim_vec,stim_0)
(stim_0
is a zero length sequence):
using ImagineInterface, Unitful
import Unitful:s
ocpi3 = rigtemplate("ocpi-2"; sample_rate = 5s^-1)
stim_com1 = getstimuli(ocpi3)[1]
nsamps_on = 10
nsamps_off = 20
stim_vec = RepeatedValue{rawtype(stim_com1)}[]
stim_on = RepeatedValue(nsamps_on, true)
stim_off = RepeatedValue(nsamps_off, false)
stim_0=RepeatedValue(0, false)
push!(stim_vec,stim_0)
push!(stim_vec, stim_on)
push!(stim_vec, stim_off)
append!(stim_com1, "on_off", stim_vec)
using Plots, ImaginePlots
plot(ocpi3)
I got
It failed to append any true
value to the stimulus channel.
If I keep the original order of push!(stim_vec, stim_on)
and push!(stim_vec,stim_0)
, and instead I set stim_0=RepeatedValue(0, true)
using ImagineInterface, Unitful
import Unitful:s
ocpi3 = rigtemplate("ocpi-2"; sample_rate = 5s^-1)
stim_com1 = getstimuli(ocpi3)[1]
nsamps_on = 10
nsamps_off = 20
stim_vec = RepeatedValue{rawtype(stim_com1)}[]
stim_on = RepeatedValue(nsamps_on, true)
stim_off = RepeatedValue(nsamps_off, false)
stim_0=RepeatedValue(0, true)
push!(stim_vec, stim_on)
push!(stim_vec,stim_0)
push!(stim_vec, stim_off)
append!(stim_com1, "on_off", stim_vec)
using Plots, ImaginePlots
plot(ocpi3)
The same problem also happens:
Is this still a problem?
Oops, didn't get the message. Reading it now.
On Sep 27, 2017 11:52 AM, "HaoyangRong" notifications@github.com wrote:
Reopened #30 https://github.com/HolyLab/ImagineInterface/issues/30.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/HolyLab/ImagineInterface/issues/30#event-1268194017, or mute the thread https://github.com/notifications/unsubscribe-auth/AE78hJvB0VhqLhpY2zIrCuQ8iTMnyMHrks5smn06gaJpZM4OqZqn .
Thanks for the detail, as always! This was actually a problem with get_samples
. It had an assumption that each RLEVector has length >=1. I have a fix, will submit the PR now.
I'll merge #48 first since I made the fix on top of that.
Should be fixed, but please reopen if not.
Hi Cody,
append!()
seems to be pretty slow when the input vector is large as we talked. The time consumption scales near linearly with the size of the input vector. I speculatecompress!()
might be the main cause. Here is my code: