diff --git a/src/MRIBuilder.jl b/src/MRIBuilder.jl
index 4f82f40d2b1220791788696a8f88d8dcaf9c07c7..de4ecbcfda25928b5212b36a8ae634e7a1d61a7e 100644
--- a/src/MRIBuilder.jl
+++ b/src/MRIBuilder.jl
@@ -7,12 +7,9 @@ include("scanners.jl")
 include("build_sequences.jl")
 include("variables.jl")
 include("building_blocks.jl")
-include("wait.jl")
-include("gradients/gradients.jl")
-include("pulses/pulses.jl")
-include("readouts/readouts.jl")
-include("overlapping/overlapping.jl")
-include("sequences.jl")
+include("components/components.jl")
+include("all_building_blocks/all_building_blocks.jl")
+include("all_sequences/all_sequences.jl")
 include("alternatives.jl")
 include("pathways.jl")
 include("helper_functions.jl")
@@ -27,26 +24,14 @@ export Scanner, B0, Siemens_Connectom, Siemens_Prisma, Siemens_Terra
 import .Variables: variables, duration, start_time, end_time, effective_time, flip_angle, amplitude, phase, frequency, bandwidth, N_left, N_right, qval, δ, rise_time, flat_time, slew_rate, gradient_strength, qvec, qval_square, slice_thickness, inverse_slice_thickness, fov, inverse_fov, voxel_size, inverse_voxel_size, resolution
 export variables, duration, start_time, end_time, effective_time, flip_angle, amplitude, phase, frequency, bandwidth, N_left, N_right, qval, δ, rise_time, flat_time, slew_rate, gradient_strength, qvec, qval_square, slice_thickness, inversne_slice_thickness, fov, inverse_fov, voxel_size, inverse_voxel_size, resolution
 
-import .BuildingBlocks: BuildingBlock, fixed, get_children_blocks, get_children_indices, make_generic
-export BuildingBlocks, fixed, get_children_blocks, get_children_indices, make_generic
+import .Components: InstantRFPulse, ConstantPulse, SincPulse, GenericPulse, InstantGradient, SingleReadout, ADC
+export InstantRFPulse, ConstantPulse, SincPulse, GenericPulse, InstantGradient, SingleReadout, ADC
 
-import .Wait: WaitBlock
-export WaitBlock
+import .AllBuildingBlocks: waveform, waveform_sequence, events, BaseBuildingBlock, BuildingBlock, Trapezoid, SliceSelect, LineReadout, SpoiltSliceSelect, Wait
+export waveform, waveform_sequence, events, BaseBuildingBlock, BuildingBlock, Trapezoid, SliceSelect, LineReadout, SpoiltSliceSelect, Wait
 
-import .Pulses: InstantRFPulseBlock, ConstantPulse, SincPulse, GenericPulse
-export InstantRFPulseBlock, ConstantPulse, SincPulse, GenericPulse
-
-import .Gradients: InstantGradientBlock
-export InstantGradientBlock
-
-import .Readouts: InstantReadout, ADC
-export InstantReadout, ADC
-
-import .Overlapping: TrapezoidGradient, SpoiltSliceSelect, interruptions, waveform, SingleLine, opposite_kspace_lines, waveform_sequence
-export TrapezoidGradient, SpoiltSliceSelect, interruptions, waveform, SingleLine, opposite_kspace_lines, waveform_sequence
-
-import .Sequences: Sequence
-export Sequence
+import .AllSequences: BaseSequence, nrepeat, Sequence
+export BaseSequence, nrepeat, Sequence
 
 import .Alternatives: AlternativeBlocks
 export AlternativeBlocks
diff --git a/src/building_blocks.jl b/src/building_blocks.jl
deleted file mode 100644
index 4d03278c70aefb661fcf16a5e8857bb07478340e..0000000000000000000000000000000000000000
--- a/src/building_blocks.jl
+++ /dev/null
@@ -1,192 +0,0 @@
-module BuildingBlocks
-import JuMP: value, Model, @constraint, @objective, objective_function, AbstractJuMPScalar
-import ..Variables: Variables, variables, start_time, duration, end_time, gradient_strength, slew_rate, effective_time, VariableType, alternative_variables, qval_square
-import ..BuildSequences: global_model, global_scanner, fixed
-import ..Scanners: Scanner
-
-"""
-Parent type for all individual components out of which a sequence can be built.
-
-Required methods:
-- [`duration`](@ref)(block, parameters): Return block duration in ms.
-- [`variables`](@ref): A list of all functions that are used to compute variables of the building block. Any of these can be used in constraints or objective functions.
-"""
-abstract type BuildingBlock end
-
-"""
-Parent type for all RF pulses.
-
-RF pulses combined with gradients, should be childrent of [`ContainerBlock`](@ref) instead.
-
-Required methods:
-- [`effective_time`](@ref)(pulse): Best approximation of time the RF pulse is applied. This is defined relative to the start of the pulse.
-"""
-abstract type RFPulseBlock <: BuildingBlock end
-
-"""
-Parent type for all gradient profiles.
-"""
-abstract type GradientBlock <: BuildingBlock end
-
-"""
-Parent type for all types combining one or more pulses/gradients.
-
-Required methods:
-- [`get_children_blocks`](@ref)(container): return all the [`BuildingBlock`](@ref) objects includes in this container.
-- [`start_time`](@ref)(container, index): returns the starting time of the child corresponding to `index` relative to the start of the `container` in ms.
-- `Base.getindex`(container, index): get child [`BuildingBlock`](@ref) corresponding to `index`.
-"""
-abstract type ContainerBlock <: BuildingBlock end
-
-
-"""
-    get_children_blocks(container)
-
-Return all the [`BuildingBlock`](@ref) objects includes in this container.
-"""
-get_children_blocks(bb::BuildingBlock) = [bb[i] for i in get_children_indices(bb)]
-
-"""
-    get_children_indices(container)
-
-Return the indices of all the children in a [`ContainerBlock`](@ref).
-
-This needs to be defined for every [`ContainerBlock`](@ref).
-"""
-function get_children_indices end
-
-
-"""
-    start_time(container, args...)
-
-Returns the starting time of the specific [`BuildingBlock`](@ref) within the container.
-The [`BuildingBlock`](@ref) is defined by one or more indices as defined below.
-"""
-start_time(bb::BuildingBlock) = 0.
-start_time(container::ContainerBlock, index1, index2, more_indices...) = start_time(container, index1) + start_time(container[index1], index2, more_indices)
-
-"""
-    effective_time(pulse)
-    effective_time(readout)
-    effective_time(container, indices...)
-
-Returns the effective time of a pulse or readout.
-
-For a pulse, this means the timepoint at which one would place an [`InstantRFPulseBlock`](@ref) if one would want to have a similar effect.
-
-For a reaodut, this is the time the readout passes through the zero-point in k-space (or the minimum in k-space if it does not go through zero).
-
-The time is given with respect to the start of the pulse or readout, or to the start of a container if the pulse/readout is identified using indices.
-"""
-effective_time(bb::ContainerBlock, index, indices...) = start_time(bb, index) + effective_time(bb[index], indices...)
-
-"""
-    end_time(container, args...)
-
-Returns the end time of the specific [`BuildingBlock`](@ref) within the container.
-The [`BuildingBlock`](@ref) is defined by one or more indices as defined below.
-"""
-end_time(bb::BuildingBlock) = duration(bb::BuildingBlock)
-end_time(container::ContainerBlock, index1, indices...) = start_time(container, index1) + end_time(container[index1], indices...)
-
-
-"""
-    to_block(object)
-
-Function used internally to convert a wide variety of objects into [`BuildingBlock`](@ref) objects.
-"""
-to_block(bb::BuildingBlock) = bb
-
-
-
-"""
-    match_blocks!(block1, block2, property_list)
-
-Matches the listed variables between two [`BuildingBlock`](@ref) objects.
-"""
-function match_blocks!(block1::BuildingBlock, block2::BuildingBlock, property_list)
-    for fn in property_list
-        @constraint global_model() fn(block1) == fn(block2)
-    end
-end
-
-"""
-    scanner_constraints!(building_block[, scanner])
-
-Adds the gradient strength and slew rate constraints from a specific [`Scanner`](@ref) to a [`BuildingBlock`]{@ref}.
-
-This is applied iteratively to each part of a `Sequence`.
-"""
-function scanner_constraints!(building_block::BuildingBlock) 
-    try
-        scanner_constraints!(building_block, global_scanner())
-    catch e
-        if occursin("No valid scanner", e.msg)
-            return
-        end
-        rethrow()
-    end
-end
-
-function scanner_constraints!(building_block::BuildingBlock, scanner::Scanner)
-    for func in [gradient_strength, slew_rate]
-        if isfinite(func(scanner))
-            scanner_constraints!(building_block, scanner, func)
-        end
-    end
-end
-
-function scanner_constraints!(building_block::BuildingBlock, scanner::Scanner, func::Function)
-    model = global_model()
-    try
-        # apply constraint at this level
-        res_bb = func(building_block)
-        if res_bb isa AbstractVector
-            if isnothing(building_block.rotate)
-                # no rotation; apply constraint to each dimension independently
-                for expr in res_bb
-                    @constraint model expr <= func(scanner)
-                    @constraint model expr >= -func(scanner)
-                end
-            else
-                # with rotation: apply constraint to total squared
-                total_squared = sum(map(n->n^2, res_bb))
-                @constraint model total_squared <= func(scanner)^2
-            end
-        else
-            @constraint model res_bb <= func(scanner)
-            @constraint model res_bb >= -func(scanner)
-        end
-
-    catch e
-        if !(e isa VariableNotAvailable)
-            rethrow()
-        end
-        if building_block isa ContainerBlock
-            for child_block in get_children_blocks(building_block)
-                scanner_constraints!(child_block, scanner, func)
-            end
-        end
-    end
-end
-
-
-function fixed(bb::BuildingBlock)
-    arguments = []
-    for name in propertynames(bb)
-        push!(arguments, fixed(getproperty(bb, name)))
-    end
-    return typeof(bb)(arguments...)
-end
-
-
-"""
-    make_generic(bb::BuildingBlock)
-
-Replaces a [`BuildingBlock`](@ref) or whole sequence with a generic version.
-
-This replaces all functional RF pulses and gradient waveforms with their generic equivalents.
-"""
-function make_generic end
-
-end
\ No newline at end of file
diff --git a/src/sequences.jl b/src/sequences.jl
deleted file mode 100644
index 68cc45d45452ae5d555bad4b8a060ec6cde8be23..0000000000000000000000000000000000000000
--- a/src/sequences.jl
+++ /dev/null
@@ -1,61 +0,0 @@
-"""
-Define the [`Sequence`](@ref) building block.
-"""
-module Sequences
-import JuMP: @constraint
-import ...BuildSequences: global_model
-import ...Variables: variables, start_time, duration, VariableType, get_free_variable, TR, end_time
-import ...BuildingBlocks: BuildingBlock, ContainerBlock, to_block, get_children_indices, fixed, fixed, make_generic
-
-"""
-    Sequence(building_blocks...; TR=nothing)
-    Sequence([building_blocks]; TR=nothing)
-
-Represents a series of [`BuildingBlock`](@ref) objects run in turn.
-
-This can be used as a top-level NMR/MRI sequence (in which case the [`TR`](@ref) variable is relevant)
-or be embedded as a [`BuildingBlock`](@ref) into higher-order `Sequence` or other [`ContainerBlock`](@ref) objects.
-
-## Variables
-- [`TR`](@ref): repetition time of sequence in ms.
-"""
-struct Sequence <: ContainerBlock
-    _blocks :: Vector{<:BuildingBlock}
-    TR :: VariableType
-    function Sequence(blocks::AbstractVector; TR=nothing)
-        seq = new(
-            to_block.(blocks),
-            get_free_variable(TR),
-        )
-        if !(TR isa Number && (isinf(TR) || duration(seq) isa Number))
-            @constraint global_model() seq.TR >= duration(seq)
-        end
-        return seq
-    end
-end
-
-Sequence(blocks...; TR=nothing) = Sequence([blocks...]; TR=TR)
-fixed(seq::Sequence) = Sequence(fixed.(seq._blocks), TR=fixed(seq.TR))
-make_generic(seq::Sequence) = Sequence(make_generic.(seq._blocks), TR=seq.TR)
-
-Base.length(seq::Sequence) = length(seq._blocks)
-Base.getindex(seq::Sequence, index) = seq._blocks[index]
-get_children_indices(seq::Sequence) = eachindex(seq._blocks)
-
-"""
-    start_time(sequence::Sequence, index::Integer, args...)
-
-Returns the starting time of the [`BuildingBlock`](@ref) with index `index`.
-Additional `args` can be used to select a sub-block of that [`BuildingBlock`](@ref).
-The starting time is returned with respect to the start of this sequence.
-"""
-start_time(seq::Sequence, index::Integer) = isone(index) ? start_time(seq) : (start_time(seq, index-1) + duration(seq[index-1]))
-
-duration(seq::Sequence) = end_time(seq, length(seq))
-
-TR(seq::Sequence) = seq.TR
-
-
-end
-
-
diff --git a/src/wait.jl b/src/wait.jl
deleted file mode 100644
index b672e95b69dea718fa45f404aa8488fa3896f32a..0000000000000000000000000000000000000000
--- a/src/wait.jl
+++ /dev/null
@@ -1,48 +0,0 @@
-module Wait
-import JuMP: @constraint, @variable, VariableRef, value
-import ..Variables: VariableType, variables, duration, get_free_variable
-import ..BuildingBlocks: BuildingBlock, to_block, make_generic
-import ..BuildSequences: global_model
-import ...Scanners: Scanner
-
-"""
-    WaitBlock(duration)
-
-An empty [`BuildingBlock`](@ref) of given `duration` (in ms).
-
-Duration can be set to one of:
-- numeric value to fix it
-- `:min` to minimise its value given any external constraints
-- `:max` to maximise its value given any external constraints
-- `nothing` to make it fully determined by external constraints and objectives
-"""
-struct WaitBlock <: BuildingBlock
-    duration :: VariableType
-    function WaitBlock(duration=nothing)
-        if duration isa Number
-            return new(duration)
-        end
-        res = new(
-            get_free_variable(duration),
-        )
-        @constraint global_model() res.duration >= 0
-        return res
-    end
-end
-
-"""
-    to_block(JuMP variable/:min or :max/nothing/number)
-
-Converts object into a [`WaitBlock`](@ref).
-- if a Number or a JuMP variable the wait time will match that value.
-- if `:min`, the wait time will be minimised in the final sequence (limited by any external constraints).
-- if `:max`, the wait time will be maximised in the final sequence (limited by any external constraints).
-- if `nothing`, the wait time is only constrained by external factors.
-"""
-to_block(time::Union{VariableType, Symbol, Nothing, Val{:min}, Val{:max}}) = WaitBlock(time)
-
-duration(wb::WaitBlock) = wb.duration
-
-make_generic(wb::WaitBlock) = wb
-
-end
\ No newline at end of file