<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def q_scan(data, mismatch=DEFAULT_MISMATCH, qrange=DEFAULT_QRANGE, frange=DEFAULT_FRANGE, duration=None, sampling=None, **kwargs):
 """Transform data by scanning over a `QTiling` This utility is provided mainly to allow direct manipulation of the `QTiling.transform` output. Most users probably just want to use :meth:`~gwpy.timeseries.TimeSeries.q_transform`, which wraps around this. Parameters data : `~gwpy.timeseries.TimeSeries` or `ndarray` the time- or frequency-domain input data mismatch : `float`, optional maximum allowed fractional mismatch between neighbouring tiles qrange : `tuple` of `float`, optional `(low, high)` range of Qs to scan frange : `tuple` of `float`, optional `(low, high)` range of frequencies to scan duration : `float`, optional duration (seconds) of input, required if `data` is not a `TimeSeries` sampling : `float`, optional sample rate (Hertz) of input, required if `data` is not a `TimeSeries` **kwargs other keyword arguments to be passed to :meth:`QTiling.transform`, including ``'epoch'`` and ``'search'`` Returns ------- qgram : `QGram` the raw output of :meth:`QTiling.transform` far : `float` expected false alarm rate (Hertz) of white Gaussian noise with the same peak energy and total duration as `qgram` """

    from gwpy.timeseries import TimeSeries
    # prepare input
    if isinstance(data, TimeSeries):
        duration = abs(data.span)
        sampling = data.sample_rate.to('Hz').value
        kwargs.update({'epoch': data.t0.value})
        data = data.fft().value
    # return a raw Q-transform and its significance
    qgram, N = QTiling(duration, sampling, mismatch=mismatch, qrange=qrange,
                       frange=frange).transform(data, **kwargs)
    far = 1.5 * N * numpy.exp(-qgram.peak['energy']) / duration
    return (qgram, far)