def expand_accidentals(volpiano, omit_notes=False, barlines='3456'):
    """Expand all accidentals in a volpiano string by adding the accidental
    to all other notes in the scope.
    
    In CANTUS transcriptions, flats are added only once, directly in front
    of the B. This function adds flat signs before all successive Bs until
    the next natural sign, or the next barline. Note that all natural signs
    are removed.

    This function does not assume that when a note is flattened, the notes an
    octave higher and lower are also flattened. (So it assumes that after a 
    central b flat `ij`, a lower b-flat `yb` indeed has an accidental)
 
    Flat/Nat. Note  Description
    --------------------------
    i/I       j     Central b flat
    y/Y       b     Low b flat
    z/Z       q     High b flat
    w/W       e     Low e flat
    x/X       m     High e flat
    
    >>> expand_accidentals('ijjj')
    'ijijij'
    >>> expand_accidentals('ijjj', omit_notes=True)
    'iii'
    >>> expand_accidentals('ij3j', omit_notes=True)
    'i3j'
    >>> expand_accidentals('ijjIjj', omit_notes=True)
    'iijj'
    >>> expand_accidentals('ijjIjj', omit_notes=False)
    'ijijjj'

    Parameters
    ----------
    volpiano : str
        The volpiano string
    omit_notes : bool, optional
        Whether to omit notes. If True, the function only returns the 
        accidentals, not the actual notes. In this case accidentals function
        as notes. By default False
    barlines : str, optional
        Volpiano characters that are barlines and therefore end the scope of
        all accidentals, by default '3456'

    Returns
    -------
    str
        A volpiano string with all flats added
    """
    in_scope = { 'i': False, 'y': False, 'z': False, 'w': False, 'x': False}
    output = ''
    for char in volpiano:
        # If the character is a flat, enter its scope
        if char in 'iyzwx': 
            in_scope[char] = True

        # If a natural, exit the corresponding flats scope
        elif char in 'IYZWX': 
            in_scope[char.lower()] = False
        
        # Reset scope on barlines (single, double, bold or middle)
        elif char in barlines:
            output += char
            for key in in_scope.keys():
                in_scope[key] = False

        # Central b flat?
        elif in_scope['i'] and char == 'j':
            output += 'i' if omit_notes else 'ij'

        # Low b flat?
        elif in_scope['y'] and char == 'b':
            output += 'y' if omit_notes else 'yb'
        
        # High b flat?
        elif in_scope['z'] and char == 'q':
            output += 'z' if omit_notes else 'zq'

        # Low e flat?
        elif in_scope['w'] and char == 'e':
            output += 'w' if omit_notes else 'we'

        # High e flat?
        elif in_scope['x'] and char == 'm':
            output += 'x' if omit_notes else 'xm'

        # Another note
        else:
            output += char
    return output