<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def channel_width(im, chanangle=None, *, chanapproxangle=None, isccsedge=False):
 """Get an estimation of the channel width. Parameters: im: 2d array The channel image chanangle: number, optional The angle of the channel (None if unknown) chanapproxangle: number, optional If chanangle is None, the approximate channel angle isccsedge: boolean, default False Set to True if im is the dft of egde. False if it is an image of a channel. Returns: -------- width: number The channel width angle: number The corresponding angle Notes: ------ This function assumes two parallel lines along angle chanangle. The perpendicular line in the fourrier plane will have a mark of this, under the form of an oscillation at some frequency corresponding to the distance between the two parallel lines. This can be extracted by another fft. This second fft might have large components at low frequency, So the first few frequencies are neglected. The threshold is the first position below mean If the chanangle is not specified, the direction with higher contribution will be picked. If chanapproxangle is given, only angles close to this angle are taken into account """

    # check input is numpy array
    im = np.asarray(im)

    # Compute the dft if it is not already done
    if not isccsedge:
        im = reg.dft_optsize(np.float32(edge(im)))

    # save the truesize for later use
    truesize = im.shape

    # get centered magnitude squared (This changes the size)
    im = reg.centered_mag_sq_ccs(im)

    # if the channel direction is not given, deduce it from channel_angle
    if chanangle is None:
        chanangle = channel_angle(im, isshiftdftedge=True,
                                  chanapproxangle=chanapproxangle,
                                  truesize=truesize)

    # get vector perpendicular to angle
    fdir = np.asarray([math.cos(chanangle), -math.sin(chanangle)])  # y,x = 0,1

    # need to be in the RHS of the cadran for rfft
    if fdir[1] < 0:
        fdir *= -1

    # get center of shifted fft
    center = np.asarray([im.shape[0] // 2, 0])

    # get size
    shape = np.asarray([im.shape[0] // 2, im.shape[1]])

    # get evenly spaced positions between 0 and 1 (not included)
    # should be replaced with linspace
    pos = np.r_[:1:(shape.min() + 1) * 1j][:-1]

    # get index of a line of length 1 in normalized units from center
    # in direction of chdir
    idx = ((fdir * shape)[:, np.newaxis].dot(pos[np.newaxis])
           + center[:, np.newaxis])

    # get the line
    idx = np.float32(idx)
    f = cv2.remap(np.float32(im), idx[1, :], idx[0, :], cv2.INTER_LINEAR)
    f = np.squeeze(f)

    # The central line of the fft will have a periodic feature for parallel
    # lines which we can detect with fft
    f = abs(irfft(f**2))
    # filter to avoid "interferences"
    f = gaussian_filter(f, 1)
    # the offset is determined by the first pixel below mean
    wmin = np.nonzero(f - f.mean() < 0)[0][0]

    """
    import matplotlib.pyplot as plt
    plt.figure()
    plt.plot(f,'x')
    plt.plot([wmin,wmin],[0,f.max()])
    plt.plot([0,500],[f.mean()+3*f.std(),f.mean()+3*f.std()])
    #"""

    # find max excluding the first few points
    ret = reg.get_peak_pos(f[wmin:f.size // 2])

    # return max and corresponding angle
    return (wmin + ret), chanangle