<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def apply_chords_3D(im, spacing=0, trim_edges=True):
 r""" Adds chords to the void space in all three principle directions. The chords are seprated by 1 voxel plus the provided spacing. Chords in the X, Y and Z directions are labelled 1, 2 and 3 resepctively. Parameters im : ND-array A 3D image of the porous material with void space marked as True. spacing : int (default = 0) Chords are automatically separed by 1 voxel on all sides, and this argument increases the separation. trim_edges : bool (default is ``True``) Whether or not to remove chords that touch the edges of the image. These chords are artifically shortened, so skew the chord length distribution Returns ------- image : ND-array A copy of ``im`` with values of 1 indicating x-direction chords, 2 indicating y-direction chords, and 3 indicating z-direction chords. Notes ----- The chords are separated by a spacing of at least 1 voxel so that tools that search for connected components, such as ``scipy.ndimage.label`` can detect individual chords. See Also -------- apply_chords """

    if im.ndim != im.squeeze().ndim:
        warnings.warn('Input image conains a singleton axis:' + str(im.shape) +
                      ' Reduce dimensionality with np.squeeze(im) to avoid' +
                      ' unexpected behavior.')
    if im.ndim < 3:
        raise Exception('Must be a 3D image to use this function')
    if spacing < 0:
        raise Exception('Spacing cannot be less than 0')
    ch = sp.zeros_like(im, dtype=int)
    ch[:, ::4+2*spacing, ::4+2*spacing] = 1  # X-direction
    ch[::4+2*spacing, :, 2::4+2*spacing] = 2  # Y-direction
    ch[2::4+2*spacing, 2::4+2*spacing, :] = 3  # Z-direction
    chords = ch*im
    if trim_edges:
        temp = clear_border(spim.label(chords > 0)[0]) > 0
        chords = temp*chords
    return chords