Skip to content
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

Feature sequential sampling models #139

Open
wants to merge 9 commits into
base: fix#124
Choose a base branch
from

Conversation

Zooaal
Copy link
Collaborator

@Zooaal Zooaal commented Feb 19, 2025

New Features:

  • New Component "Drift_Component" which is used for simulating evidence accumulation process with different Models.
  • 3 Models for the usage in "Drift_Component": LBA, DDM and Kelly Model.
  • Functions to simulate the models traces and response times.
  • New Onset "SequenceOnset" which can be used with SequenceDesign to define a Onset for each Component in a Sequence.
  • New Onset "DriftOnset" special onset for the Drift_Component.
  • simulate_interonset_distances Functions for the "DriftOnset" used to return the response times of the models used.
  • simulate_onsets Function for the "SequenceOnset" specifies how the onsets for the sequences are calculated defined by the Onset for each Component. Important here: Onsets are defined for the next Component. For Example "SCR"=> S->C, C->R and R->S
  • New File "sequentialSamplingModelSimulation.jl": Defines the Kelly Model and its simulation. Furthermore the simulation of the LBA and DDM are designed. In the Future more Models can be defined here.

Important Changes:

  • Added using of SepuentialSamplingModels Package

On Top I added unittests and docstrings for all new features

For better usability I have created two HowTo in the documentation:

  • One explains how to simulate an entire evidence accumulation process as a basis.
  • Another one explains how to use the KellyModel, how to define parameters in the design and how to simulate an overlap of components.

@Zooaal Zooaal requested review from behinger and jschepers February 19, 2025 15:25
@behinger behinger changed the base branch from main to exponential-noise February 21, 2025 11:05
@behinger behinger marked this pull request as ready for review February 21, 2025 11:05
@behinger behinger changed the base branch from exponential-noise to fix#124 February 21, 2025 11:06
Copy link
Member

@behinger behinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an intermediate review, I'm running out of time, but I didnt check everything yet

Wording DocString

Co-authored-by: Benedikt Ehinger <[email protected]>
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remaining comments which cannot be posted as a review comment to avoid GitHub Rate Limit

JuliaFormatter

[JuliaFormatter] reported by reviewdog 🐶


[JuliaFormatter] reported by reviewdog 🐶

drift_rate::Union{Real, String} # drift rate
event_onset::Union{Real, String} # onset(sensory evidence)
sensor_encoding_delay::Union{Real, String} # var(sensory encoding delay)
accumulative_level_noise::Union{Real, String} # accum level noise
boundary::Union{Real, String} # boundaryary height
motor_onset::Union{Real, String} # onset(motor)
motor_delay::Union{Real, String} # var(motor)
post_accumulation_duration_mean::Union{Real, String} # mean(post decision)
post_accumulation_duration_variability::Union{Real, String} # var(post decision)
CPPrampdownDur::Union{Real, String} # CPPrampdown duration


[JuliaFormatter] reported by reviewdog 🐶


[JuliaFormatter] reported by reviewdog 🐶

return new(drift_rate, event_onset, sensor_encoding_delay, accumulative_level_noise, boundary, motor_onset,
motor_delay, post_accumulation_duration_mean, post_accumulation_duration_variability,
CPPrampdownDur)


[JuliaFormatter] reported by reviewdog 🐶

return Dict(
name => getfield(model, name) for name in fieldnames(typeof(model))
)


[JuliaFormatter] reported by reviewdog 🐶

evidence = zeros(length(time_vec));
evidence[time_vec .>= (model.event_onset+(rand(rng) -.5)*model.sensor_encoding_delay)] .= 1;
startAccT = time_vec[findfirst(evidence .== 1)];
noise = vcat(zeros(
sum(time_vec .< startAccT)),
randn(rng,sum(time_vec .>= startAccT)) .* model.accumulative_level_noise .*sqrt(Δt));
ev=evidence;
ev[time_vec .< startAccT] .= 0; # set to zero all of the evidence before accT
cum_evidence = cumsum(ev .* model.drift_rate .* Δt .+ noise,dims=1); # This is the cumulative differential evidence, just as in a 1d DDM.


[JuliaFormatter] reported by reviewdog 🐶

cum_evidence = abs.(cum_evidence);
dti = findfirst(cum_evidence .> model.boundary); # finding the sample point of threshold crossing of each, then will pick the earlier as the winner


[JuliaFormatter] reported by reviewdog 🐶

rt = time_vec[dti] + model.motor_onset + (rand(rng)-.5) * model.motor_delay;


[JuliaFormatter] reported by reviewdog 🐶

post_acc_duration = model.post_accumulation_duration_mean .+ model.post_accumulation_duration_variability .* rand(rng);


[JuliaFormatter] reported by reviewdog 🐶

acc_stop_index = dti + (post_acc_duration÷Δt)|>Int;


[JuliaFormatter] reported by reviewdog 🐶

cum_evidence = abs.(cum_evidence);
if acc_stop_index<length(time_vec)


[JuliaFormatter] reported by reviewdog 🐶

tmp = cum_evidence[acc_stop_index] .- (1:(nT-acc_stop_index)) .*cum_evidence[acc_stop_index] .* (Δt ./ model.CPPrampdownDur)
cum_evidence[(acc_stop_index+1):end] .= max.(Ref(0), tmp);


[JuliaFormatter] reported by reviewdog 🐶

return rt/Δt, cum_evidence[1:end]


[JuliaFormatter] reported by reviewdog 🐶

function trace_sequential_sampling_model(rng, component::Drift_Component, design::AbstractDesign)


[JuliaFormatter] reported by reviewdog 🐶

model = component.model_type(; (key => parameters[key] for key in keys(parameters))...)


[JuliaFormatter] reported by reviewdog 🐶

rt = (time_steps[end] + model.τ)/Δt


[JuliaFormatter] reported by reviewdog 🐶

rt = (time_vec[end] + model.τ)/Δt


[JuliaFormatter] reported by reviewdog 🐶

rt = (time_steps[end] + model.τ)/Δt


[JuliaFormatter] reported by reviewdog 🐶


[JuliaFormatter] reported by reviewdog 🐶

# Test UnfoldSim.simulate_component(rng, c::Drift_Component, design::AbstractDesign)
boundary = 1.0
model_parameter = UnfoldSim.create_kelly_parameters_dict(UnfoldSim.KellyModel(boundary=boundary));
c = Drift_Component(simulate_component, 0:1/500:1.0, 1/500, KellyModel, model_parameter);
design_single = UnfoldSim.SingleSubjectDesign(conditions = Dict(:condition => [1]));
design_seq = UnfoldSim.SequenceDesign(design_single,"SCR_");
result_traces = UnfoldSim.simulate_component(StableRNG(1),c,design_seq)
@test size(result_traces) == (501, 3)
@test any(result_traces .== 0)
@test any(result_traces .>= boundary)


[JuliaFormatter] reported by reviewdog 🐶

# Test UnfoldSim.simulate_component(rng, c::Drift_Component, design::AbstractDesign)
boundary = 1.0
model_parameter = UnfoldSim.create_kelly_parameters_dict(UnfoldSim.KellyModel(boundary=boundary));
c = Drift_Component(simulate_component, 0:1/500:1.0, 1/500, KellyModel, model_parameter);
design_single = UnfoldSim.SingleSubjectDesign(conditions = Dict(:drift_rate => [0.5, 0.8], :condition => [1]));
design_seq = UnfoldSim.SequenceDesign(design_single,"SCR_");
result_traces = UnfoldSim.simulate_component(StableRNG(1),c,design_seq)


[JuliaFormatter] reported by reviewdog 🐶

@test size(result_traces) == (501, 6)
@test any(result_traces .== 0)
@test any(result_traces .>= boundary)


[JuliaFormatter] reported by reviewdog 🐶

# Test calculate_response_times_for_ssm(rng, component::Drift_Component, design::AbstractDesign)
model_parameter = UnfoldSim.create_kelly_parameters_dict(UnfoldSim.KellyModel());
c = Drift_Component(simulate_component, 0:1/500:1.0, 1/500, KellyModel, model_parameter);
design_single = UnfoldSim.SingleSubjectDesign(conditions = Dict(:drift_rate => [0.5, 0.8], :condition => [1]));
design_seq = UnfoldSim.SequenceDesign(design_single,"SCR_");
sub_design = UnfoldSim.SubselectDesign(design_seq, 'C')
result_rts = UnfoldSim.calculate_response_times_for_ssm(StableRNG(1),c,sub_design)
@test size(result_rts) == (2,)
@test isapprox(result_rts, [399.6903067274333, 388.89617910657597], atol=1e-8)


[JuliaFormatter] reported by reviewdog 🐶

# Test get_model_parameter(rng, evt, d::Dict)
rng = StableRNG(1)
model_parameter = UnfoldSim.create_kelly_parameters_dict(UnfoldSim.KellyModel(drift_rate="drift_rate"));
c = Drift_Component(simulate_component, 0:1/500:1.0, 1/500, KellyModel, model_parameter);
drift_rates = [0.5, 0.8]
design_single = UnfoldSim.SingleSubjectDesign(conditions = Dict(:drift_rate => drift_rates, :condition => [1]));
events = UnfoldSim.generate_events(rng, design_single)
for (i, evt) in enumerate(eachrow(events))


[JuliaFormatter] reported by reviewdog 🐶


[JuliaFormatter] reported by reviewdog 🐶

fs=500


[JuliaFormatter] reported by reviewdog 🐶

UnfoldSim.jl/test/onset.jl

Lines 123 to 127 in a0f9253

Dict('S'=>UniformOnset(width=0,offset=80),
'C'=>DriftOnset(),
'R'=>UniformOnset(width=0,offset=120)))
model_parameter = UnfoldSim.create_kelly_parameters_dict(UnfoldSim.KellyModel(drift_rate="drift_rate"));
c = UnfoldSim.Drift_Component(simulate_component, 0:1/500:1.0, 1/500, KellyModel, model_parameter);


[JuliaFormatter] reported by reviewdog 🐶

UnfoldSim.jl/test/onset.jl

Lines 129 to 130 in a0f9253

design_single = UnfoldSim.SingleSubjectDesign(conditions = Dict(:drift_rate => [0.5, 0.8], :condition => [1]));
design_seq = UnfoldSim.SequenceDesign(design_single,"SCR_");


[JuliaFormatter] reported by reviewdog 🐶

simulation = UnfoldSim.Simulation(design_rep, components, sequence_onset, UnfoldSim.NoNoise())


[JuliaFormatter] reported by reviewdog 🐶

UnfoldSim.jl/test/onset.jl

Lines 143 to 146 in a0f9253

Dict('S'=>UniformOnset(width=0,offset=80),
'C'=>(DriftOnset(), UniformOnset(width=0, offset=140)),
'R'=>UniformOnset(width=0,offset=120)))
simulation = UnfoldSim.Simulation(design_rep, components, sequence_onset, UnfoldSim.NoNoise())


[JuliaFormatter] reported by reviewdog 🐶


[JuliaFormatter] reported by reviewdog 🐶

time_vec = 0:Δt:tEnd; # time base


[JuliaFormatter] reported by reviewdog 🐶

km = KellyModel(event_onset=assert_event_onset, drift_rate=assert_drift_rate);


[JuliaFormatter] reported by reviewdog 🐶

result_rt, result_trace = UnfoldSim.KellyModel_simulate_cpp(rng, KellyModel(boundary=boundary), time_vec, Δt)


[JuliaFormatter] reported by reviewdog 🐶

@test isapprox(result_rt, 399.6903067274333, atol=1e-8)


[JuliaFormatter] reported by reviewdog 🐶

result_sim_rt, result_sim_trace = UnfoldSim.SSM_Simulate(rng, KellyModel(), Δt, time_vec)


[JuliaFormatter] reported by reviewdog 🐶

model_parameter = UnfoldSim.create_kelly_parameters_dict(KellyModel(boundary=boundary));
c = UnfoldSim.Drift_Component(simulate_component, time_vec, Δt, KellyModel, model_parameter);
design_single = UnfoldSim.SingleSubjectDesign(conditions = Dict(:drift_rate => [0.5, 0.8], :condition => [1]));
design_seq = UnfoldSim.SequenceDesign(design_single,"SCR_");


[JuliaFormatter] reported by reviewdog 🐶

result_rts, result_traces = UnfoldSim.trace_sequential_sampling_model(rng, c, design_seq)


[JuliaFormatter] reported by reviewdog 🐶

result_rt, result_trace = UnfoldSim.SSM_Simulate(deepcopy(rng), KellyModel(), Δt, time_vec)


[JuliaFormatter] reported by reviewdog 🐶

@test isapprox(result_rt, 399.6903067274333, atol=1e-8)


[JuliaFormatter] reported by reviewdog 🐶

@test isapprox(result_rt, 223.00000000000003, atol=1e-8)


[JuliaFormatter] reported by reviewdog 🐶

@test isapprox(result_rt, 397.0, atol=1e-8)

Co-authored-by: Benedikt Ehinger <[email protected]>
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remaining comments which cannot be posted as a review comment to avoid GitHub Rate Limit

JuliaFormatter

[JuliaFormatter] reported by reviewdog 🐶


[JuliaFormatter] reported by reviewdog 🐶

time_vec = 0:Δt:tEnd; # time base


[JuliaFormatter] reported by reviewdog 🐶

km = KellyModel(event_onset=assert_event_onset, drift_rate=assert_drift_rate);


[JuliaFormatter] reported by reviewdog 🐶

result_rt, result_trace = UnfoldSim.KellyModel_simulate_cpp(rng, KellyModel(boundary=boundary), time_vec, Δt)


[JuliaFormatter] reported by reviewdog 🐶

@test isapprox(result_rt, 399.6903067274333, atol=1e-8)


[JuliaFormatter] reported by reviewdog 🐶

result_sim_rt, result_sim_trace = UnfoldSim.SSM_Simulate(rng, KellyModel(), Δt, time_vec)


[JuliaFormatter] reported by reviewdog 🐶

model_parameter = UnfoldSim.create_kelly_parameters_dict(KellyModel(boundary=boundary));
c = UnfoldSim.Drift_Component(simulate_component, time_vec, Δt, KellyModel, model_parameter);
design_single = UnfoldSim.SingleSubjectDesign(conditions = Dict(:drift_rate => [0.5, 0.8], :condition => [1]));
design_seq = UnfoldSim.SequenceDesign(design_single,"SCR_");


[JuliaFormatter] reported by reviewdog 🐶

result_rts, result_traces = UnfoldSim.trace_sequential_sampling_model(rng, c, design_seq)


[JuliaFormatter] reported by reviewdog 🐶

result_rt, result_trace = UnfoldSim.SSM_Simulate(deepcopy(rng), KellyModel(), Δt, time_vec)


[JuliaFormatter] reported by reviewdog 🐶

@test isapprox(result_rt, 399.6903067274333, atol=1e-8)


[JuliaFormatter] reported by reviewdog 🐶

@test isapprox(result_rt, 223.00000000000003, atol=1e-8)


[JuliaFormatter] reported by reviewdog 🐶

@test isapprox(result_rt, 397.0, atol=1e-8)

Zooaal and others added 2 commits February 25, 2025 11:06
Formatting

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Formatting

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
data_epochs,
);
results = coeftable(m)
plot_erp(results; mapping = (; color = :eventname))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
plot_erp(results; mapping = (; color = :eventname))
plot_erp(results; mapping = (; color = :eventname))

data,
);
results = coeftable(m)
plot_erp(results; mapping = (; color = :eventname))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
plot_erp(results; mapping = (; color = :eventname))
plot_erp(results; mapping = (; color = :eventname))

```
"""
function SSM_Simulate(rng, model::KellyModel, sfreq, max_length)
Δt = 1/sfreq
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
Δt = 1/sfreq
Δt = 1 / sfreq

evidence = evidence[1:max_length]
end
return rt, evidence
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
end
end

Comment on lines +49 to +59
# Test UnfoldSim.simulate_component(rng, c::DriftComponent, design::AbstractDesign)
boundary = 1.0
model_parameter = Dict(:boundary => boundary);
c = DriftComponent(500, 500, KellyModel, model_parameter);
design_single = UnfoldSim.SingleSubjectDesign(conditions = Dict(:condition => [1]));
design_seq = UnfoldSim.SequenceDesign(design_single,"SCR_");
result_traces = UnfoldSim.simulate_component(StableRNG(1),c,design_seq)

@test size(result_traces) == (501, 3)
@test any(result_traces .== 0)
@test any(result_traces .>= boundary)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
# Test UnfoldSim.simulate_component(rng, c::DriftComponent, design::AbstractDesign)
boundary = 1.0
model_parameter = Dict(:boundary => boundary);
c = DriftComponent(500, 500, KellyModel, model_parameter);
design_single = UnfoldSim.SingleSubjectDesign(conditions = Dict(:condition => [1]));
design_seq = UnfoldSim.SequenceDesign(design_single,"SCR_");
result_traces = UnfoldSim.simulate_component(StableRNG(1),c,design_seq)
@test size(result_traces) == (501, 3)
@test any(result_traces .== 0)
@test any(result_traces .>= boundary)
# Test UnfoldSim.simulate_component(rng, c::DriftComponent, design::AbstractDesign)
boundary = 1.0
model_parameter = Dict(:boundary => boundary)
c = DriftComponent(500, 500, KellyModel, model_parameter)
design_single = UnfoldSim.SingleSubjectDesign(conditions = Dict(:condition => [1]))
design_seq = UnfoldSim.SequenceDesign(design_single, "SCR_")
result_traces = UnfoldSim.simulate_component(StableRNG(1), c, design_seq)

Comment on lines +38 to +44
model_parameter = Dict(:boundary => boundary);
c = UnfoldSim.DriftComponent(
max_length,
fs,
KellyModel,
model_parameter,
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
model_parameter = Dict(:boundary => boundary);
c = UnfoldSim.DriftComponent(
max_length,
fs,
KellyModel,
model_parameter,
)
model_parameter = Dict(:boundary => boundary)
c = UnfoldSim.DriftComponent(max_length, fs, KellyModel, model_parameter)

)
design_seq = UnfoldSim.SequenceDesign(design_single, "SCR_")

result_rts, result_traces = UnfoldSim.trace_sequential_sampling_model(rng, c, design_seq)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
result_rts, result_traces = UnfoldSim.trace_sequential_sampling_model(rng, c, design_seq)
result_rts, result_traces =
UnfoldSim.trace_sequential_sampling_model(rng, c, design_seq)

end

@testset "SSM_Simulate" begin
result_rt, result_trace = UnfoldSim.SSM_Simulate(deepcopy(rng), KellyModel(), fs, max_length)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
result_rt, result_trace = UnfoldSim.SSM_Simulate(deepcopy(rng), KellyModel(), fs, max_length)
result_rt, result_trace =
UnfoldSim.SSM_Simulate(deepcopy(rng), KellyModel(), fs, max_length)

@test any(result_trace .== 0)
@test any(result_trace .>= boundary)

result_rt, result_trace = UnfoldSim.SSM_Simulate(deepcopy(rng), DDM(), fs, max_length)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
result_rt, result_trace = UnfoldSim.SSM_Simulate(deepcopy(rng), DDM(), fs, max_length)
result_rt, result_trace =
UnfoldSim.SSM_Simulate(deepcopy(rng), DDM(), fs, max_length)

@test isapprox(result_rt, 223.00000000000003, atol = 1e-8)
@test any(result_trace .== 0)

result_rt, result_trace = UnfoldSim.SSM_Simulate(deepcopy(rng), LBA(), fs, max_length)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
result_rt, result_trace = UnfoldSim.SSM_Simulate(deepcopy(rng), LBA(), fs, max_length)
result_rt, result_trace =
UnfoldSim.SSM_Simulate(deepcopy(rng), LBA(), fs, max_length)

Comment on lines +53 to +55
return new(drift_rate, event_onset, sensor_encoding_delay, accumulative_level_noise, boundary, motor_onset,
motor_delay, post_accumulation_duration, post_accumulation_duration_variability,
ramp_down_duration)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
return new(drift_rate, event_onset, sensor_encoding_delay, accumulative_level_noise, boundary, motor_onset,
motor_delay, post_accumulation_duration, post_accumulation_duration_variability,
ramp_down_duration)
return new(
drift_rate,
event_onset,
sensor_encoding_delay,
accumulative_level_noise,
boundary,
motor_onset,
motor_delay,
post_accumulation_duration,
post_accumulation_duration_variability,
ramp_down_duration,
)

rt = time_vec[dti] + model.motor_onset + (rand(rng) - 0.5) * model.motor_delay

# now make the CPP peak and go down linearly after a certain amount of post-dec accum time for this trial:
post_acc_duration = model.post_accumulation_duration .+ model.post_accumulation_duration_variability .* rand(rng);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
post_acc_duration = model.post_accumulation_duration .+ model.post_accumulation_duration_variability .* rand(rng);
post_acc_duration =
model.post_accumulation_duration .+
model.post_accumulation_duration_variability .* rand(rng)

Comment on lines +140 to +141
tmp = cum_evidence[acc_stop_index] .- (1:(nT-acc_stop_index)) .*cum_evidence[acc_stop_index] .* (Δt ./ model.ramp_down_duration)
cum_evidence[(acc_stop_index+1):end] .= max.(Ref(0), tmp);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
tmp = cum_evidence[acc_stop_index] .- (1:(nT-acc_stop_index)) .*cum_evidence[acc_stop_index] .* (Δt ./ model.ramp_down_duration)
cum_evidence[(acc_stop_index+1):end] .= max.(Ref(0), tmp);
tmp =
cum_evidence[acc_stop_index] .-
(1:(nT-acc_stop_index)) .* cum_evidence[acc_stop_index] .*
(Δt ./ model.ramp_down_duration)
cum_evidence[(acc_stop_index+1):end] .= max.(Ref(0), tmp)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants