From 185b857a9795d35bc1c5628d3721b949c5328d9f Mon Sep 17 00:00:00 2001 From: Michiel Cottaar <michiel.cottaar@ndcn.ox.ac.uk> Date: Thu, 15 Feb 2024 15:16:48 +0000 Subject: [PATCH] Adjust iteration to go across multiple repeats --- src/all_sequences/base_sequences.jl | 47 ++++++++++++++++++++++++----- src/all_sequences/sequences.jl | 6 ++-- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/all_sequences/base_sequences.jl b/src/all_sequences/base_sequences.jl index 24ceedf..e610e7b 100644 --- a/src/all_sequences/base_sequences.jl +++ b/src/all_sequences/base_sequences.jl @@ -1,7 +1,7 @@ module BaseSequences import ...ContainerBlocks: ContainerBlock import ...AllBuildingBlocks: BaseBuildingBlock -import ...Variables: TR, duration +import ...Variables: TR, duration, start_time """ Super-type of any sequence of non-overlapping building blocks that should be played after each other. @@ -11,27 +11,58 @@ It contains `N` [`ContainerBlock`](@ref) objects (e.g., building blocks or other Main interface: - Acts as an iterable containing the blocks and sequences. - Indiviual blocks/sequences can be obtained using indexing. + - If there is a finite number of repeats, the iteration will continue over all repeats. Sub-types need to implement: -- `Base.getindex`: returns the actual component for each integer index in 1:N. +- `get_index_single_TR`: return the index assuming it is between 1 and N +- [`nrepeat`](@ref): how often the sequence should repeat (if not implemented, this will be 1). +- [`TR`](@ref): time scale on which to repeat (if not implemented, this will be the sum of the individual block durations). """ abstract type BaseSequence{N} <: ContainerBlock end - +function Base.getindex(bs::BaseSequence{N}, index::Integer) where {N} + if index < 1 || index > length(bs) + throw(BoundsError(bs, index)) + end + base_index = ((index - 1) % N) + 1 + return get_index_single_TR(bs, base_index) +end Base.iterate(bs::BaseSequence) = Base.iterate(bs, 1) -Base.iterate(bs::BaseSequence{N}, index::Integer) where {N} = index > N ? nothing : (bs[index], index + 1) -Base.length(::BaseSequence{N}) where {N} = N +Base.iterate(bs::BaseSequence{N}, index::Integer) where {N} = index > length(bs) ? nothing : (bs[index], index + 1) +Base.length(bs::BaseSequence{N}) where {N} = nrepeat(bs) * N Base.eltype(::Type{<:BaseSequence}) = ContainerBlock +function start_time(bs::BaseSequence{N}, index::Integer) where {N} + nTR = div(index-1, N, RoundDown) + if 0 < nrepeat(bs) <= nTR + throw(BoundsError(bs, index)) + end + base_index = ((index - 1) % N) + 1 + base_time = sum(i -> duration(bs[i]), 1:base_index) + if iszero(nTR) + return base_time + else + return nTR * TR(bs) + base_time + end +end + + +""" + get_index_single_TR(sequence, index) + +Used internally by any [`BaseSequence`](@ref) to get a specific block. +The `index` should be between 1 and N. +It should be implemented for any sub-classes of [`BaseSequence`](@ref). +""" +function get_index_single_TR end + """ nrepeat(sequence) How often sequence should be repeated. - -Set to 0 to repeat indefinetely (default value if not overriden for a particular sequence type). """ -nrepeat(bs::BaseSequence) = 0 +nrepeat(bs::BaseSequence) = 1 """ TR(sequence) diff --git a/src/all_sequences/sequences.jl b/src/all_sequences/sequences.jl index 81062be..af67159 100644 --- a/src/all_sequences/sequences.jl +++ b/src/all_sequences/sequences.jl @@ -5,7 +5,7 @@ import ...Variables: get_free_variable, TR, VariableType import ...AllBuildingBlocks: Wait, BuildingBlock import ...BuildSequences: global_model import ...Components: EventComponent -import ..BaseSequences: ContainerBlock, BaseSequence, nrepeat +import ..BaseSequences: ContainerBlock, BaseSequence, nrepeat, get_index_single_TR """ Sequence(blocks; TR=:min, nrepeat=0) @@ -35,7 +35,9 @@ end Sequence(blocks...; kwargs...) = Sequence([blocks...]; kwargs...) -Base.getindex(s::Sequence, i::Integer) = s.blocks[i] +get_index_single_TR(s::Sequence, i::Integer) = s.blocks[i] +Base.IteratorSize(::Type{<:Sequence}) = Base.IsInfinite() +nrepeat(::Sequence) = Inf """ to_block(block_like) -- GitLab