示例#1
0
def apply_filter_data(fname,raw=None,filter_method="mne",filter_type='bp',fcut1=1.0,fcut2=45.0,notch=None,notch_max=None,order=4,
                      remove_dcoffset = False,njobs=1,overwrite = False,do_run=True,verbose=False,save=True,picks=None,
                      fif_postfix=None, fif_extention='-raw.fif'):
    ''' 
    Applies the FIR FFT filter [bp,hp,lp,notches] to data array. 
    filter_method : mne => fft mne-filter
                    bw  => fft butterwoth
                    ws  => fft - windowed sinc 
    '''
            
    from jumeg.filter import jumeg_filter
   
 #--- define filter 
    jfilter = jumeg_filter(filter_method=filter_method,filter_type=filter_type,fcut1=fcut1,fcut2=fcut2,njobs=njobs, 
                                remove_dcoffset=True,order=order)
    jfilter.verbose = verbose                     

    if do_run :
       if raw is None:
          if fname is None:
             print"ERROR no file foumd!!\n" 
             return 
          raw = mne.io.Raw(fname,preload=True)
          print"\n"

       if picks is None :
          picks = jumeg_base.pick_channels_nobads(raw)
          
    #- apply filter for picks, exclude stim,resp,bads
       jfilter.sampling_frequency = raw.info['sfreq']
    #--- calc notch array 50,100,150 .. max
       if notch :
          jfilter.calc_notches(notch,notch_max)

       jfilter.apply_filter(raw._data,picks=picks )
       jfilter.update_info_filter_settings(raw)

    #--- make output filename
       name_raw = fname.split('-')[0]
       fnfilt   = name_raw + "," + jfilter.filter_name_postfix + fif_extention

       raw.info['filename'] = fnfilt

       if save :
          fnfilt = jumeg_base.apply_save_mne_data(raw,fname=fnfilt)


    else:
     #--- calc notch array 50,100,150 .. max
       if notch :
          jfilter.calc_notches(notch,notch_max)

     #--- make output filename
       name_raw = fname.split('-')[0]
       fnfilt   = name_raw + "," + jfilter.filter_name_postfix + fif_extention


    return (fnfilt, raw)
def noise_reducer_4raw_data(fname_raw,
                            raw=None,
                            signals=[],
                            noiseref=[],
                            detrending=None,
                            tmin=None,
                            tmax=None,
                            reflp=None,
                            refhp=None,
                            refnotch=None,
                            exclude_artifacts=True,
                            checkresults=True,
                            fif_extention="-raw.fif",
                            fif_postfix="nr",
                            reject={
                                'grad': 4000e-13,
                                'mag': 4e-12,
                                'eeg': 40e-6,
                                'eog': 250e-6
                            },
                            complementary_signal=False,
                            fnout=None,
                            verbose=False,
                            save=True):
    """Apply noise reduction to signal channels using reference channels.
        
       !!! ONLY ONE RAW Obj Interface Version FB !!!
           
    Parameters
    ----------
    fname_raw : rawfile name

    raw     : fif raw object

    signals : list of string
              List of channels to compensate using noiseref.
              If empty use the meg signal channels.
    noiseref : list of string | str
              List of channels to use as noise reference.
              If empty use the magnetic reference channsls (default).
    signals and noiseref may contain regexp, which are resolved
    using mne.pick_channels_regexp(). All other channels are copied.
    tmin : lower latency bound for weight-calc [start of trace]
    tmax : upper latency bound for weight-calc [ end  of trace]
           Weights are calc'd for (tmin,tmax), but applied to entire data set
    refhp : high-pass frequency for reference signal filter [None]
    reflp :  low-pass frequency for reference signal filter [None]
            reflp < refhp: band-stop filter
            reflp > refhp: band-pass filter
            reflp is not None, refhp is None: low-pass filter
            reflp is None, refhp is not None: high-pass filter
    refnotch : (base) notch frequency for reference signal filter [None]
               use raw(ref)-notched(ref) as reference signal
    exclude_artifacts: filter signal-channels thru _is_good() [True]
                       (parameters are at present hard-coded!)
    complementary_signal : replaced signal by traces that would be subtracted [False]
                           (can be useful for debugging)
    checkresults : boolean to control internal checks and overall success [True]

    reject =  dict for rejection threshold 
              units:
              grad:    T / m (gradiometers)
              mag:     T (magnetometers)
              eeg/eog: uV (EEG channels)
              default=>{'grad':4000e-13,'mag':4e-12,'eeg':40e-6,'eog':250e-6}
              
    save : save data to fif file

    Outputfile:
    -------
    <wawa>,nr-raw.fif for input <wawa>-raw.fif

    Returns
    -------
    TBD

    Bugs
    ----
    - artifact checking is incomplete (and with arb. window of tstep=0.2s)
    - no accounting of channels used as signal/reference
    - non existing input file handled ungracefully
    """

    tc0 = time.clock()
    tw0 = time.time()

    if type(complementary_signal) != bool:
        raise ValueError("Argument complementary_signal must be of type bool")

    raw, fname_raw = jumeg_base.get_raw_obj(fname_raw, raw=raw)

    if detrending:
        raw = perform_detrending(None, raw=raw, save=False)

    tc1 = time.clock()
    tw1 = time.time()

    if verbose:
        print ">>> loading raw data took %.1f ms (%.2f s walltime)" % (
            1000. * (tc1 - tc0), (tw1 - tw0))

    # Time window selection
    # weights are calc'd based on [tmin,tmax], but applied to the entire data set.
    # tstep is used in artifact detection
    # tmin,tmax variables must not be changed here!
    if tmin is None:
        itmin = 0
    else:
        itmin = int(floor(tmin * raw.info['sfreq']))
    if tmax is None:
        itmax = raw.last_samp
    else:
        itmax = int(ceil(tmax * raw.info['sfreq']))

    if itmax - itmin < 2:
        raise ValueError(
            "Time-window for noise compensation empty or too short")

    if verbose:
        print ">>> Set time-range to [%7.3f,%7.3f]" % \
              (raw.index_as_time(itmin)[0], raw.index_as_time(itmax)[0])

    if signals is None or len(signals) == 0:
        sigpick = jumeg_base.pick_meg_nobads(raw)
    else:
        sigpick = channel_indices_from_list(raw.info['ch_names'][:], signals,
                                            raw.info.get('bads'))
    nsig = len(sigpick)
    if nsig == 0:
        raise ValueError("No channel selected for noise compensation")

    if noiseref is None or len(noiseref) == 0:
        # References are not limited to 4D ref-chans, but can be anything,
        # incl. ECG or powerline monitor.
        if verbose:
            print ">>> Using all refchans."

        refexclude = "bads"
        refpick = jumeg_base.pick_ref_nobads(raw)
    else:
        refpick = channel_indices_from_list(raw.info['ch_names'][:], noiseref,
                                            raw.info.get('bads'))
    nref = len(refpick)
    if nref == 0:
        raise ValueError("No channel selected as noise reference")

    if verbose:
        print ">>> sigpick: %3d chans, refpick: %3d chans" % (nsig, nref)

    if reflp is None and refhp is None and refnotch is None:
        use_reffilter = False
        use_refantinotch = False
    else:
        use_reffilter = True
        if verbose:
            print "########## Filter reference channels:"

        use_refantinotch = False
        if refnotch is not None:
            if reflp is None and reflp is None:
                use_refantinotch = True
                freqlast = np.min([5.01 * refnotch, 0.5 * raw.info['sfreq']])
                if verbose:
                    print ">>> notches at freq %.1f and harmonics below %.1f" % (
                        refnotch, freqlast)
            else:
                raise ValueError("Cannot specify notch- and high-/low-pass"
                                 "reference filter together")
        else:
            if verbose:
                if reflp is not None:
                    print ">>>  low-pass with cutoff-freq %.1f" % reflp
                if refhp is not None:
                    print ">>> high-pass with cutoff-freq %.1f" % refhp

        # Adapt followg drop-chans cmd to use 'all-but-refpick'
        droplist = [
            raw.info['ch_names'][k] for k in xrange(raw.info['nchan'])
            if not k in refpick
        ]
        tct = time.clock()
        twt = time.time()
        fltref = raw.drop_channels(droplist, copy=True)
        if use_refantinotch:
            rawref = raw.drop_channels(droplist, copy=True)
            freqlast = np.min([5.01 * refnotch, 0.5 * raw.info['sfreq']])
            fltref.notch_filter(np.arange(refnotch, freqlast, refnotch),
                                picks=np.array(xrange(nref)),
                                method='iir')
            fltref._data = (rawref._data - fltref._data)
        else:
            fltref.filter(refhp,
                          reflp,
                          picks=np.array(xrange(nref)),
                          method='iir')
        tc1 = time.clock()
        tw1 = time.time()
        if verbose:
            print ">>> filtering ref-chans  took %.1f ms (%.2f s walltime)" % (
                1000. * (tc1 - tct), (tw1 - twt))

    if verbose:
        print "########## Calculating sig-ref/ref-ref-channel covariances:"
    # Calculate sig-ref/ref-ref-channel covariance:
    # (there is no need to calc inter-signal-chan cov,
    #  but there seems to be no appropriat fct available)
    # Here we copy the idea from compute_raw_data_covariance()
    # and truncate it as appropriate.
    tct = time.clock()
    twt = time.time()
    # The following reject and infosig entries are only
    # used in _is_good-calls.
    # _is_good() from mne-0.9.git-py2.7.egg/mne/epochs.py seems to
    # ignore ref-channels (not covered by dict) and checks individual
    # data segments - artifacts across a buffer boundary are not found.

    #--- !!! FB put to kwargs

    #reject = dict(grad=4000e-13, # T / m (gradiometers)
    #              mag=4e-12,     # T (magnetometers)
    #              eeg=40e-6,     # uV (EEG channels)
    #              eog=250e-6)    # uV (EOG channels)

    infosig = copy.copy(raw.info)
    infosig['chs'] = [raw.info['chs'][k] for k in sigpick]
    infosig['ch_names'] = [raw.info['ch_names'][k] for k in sigpick]
    infosig['nchan'] = len(sigpick)
    idx_by_typesig = channel_indices_by_type(infosig)

    # Read data in chunks:
    tstep = 0.2
    itstep = int(ceil(tstep * raw.info['sfreq']))
    sigmean = 0
    refmean = 0
    sscovdata = 0
    srcovdata = 0
    rrcovdata = 0
    n_samples = 0

    for first in range(itmin, itmax, itstep):
        last = first + itstep
        if last >= itmax:
            last = itmax
        raw_segmentsig, times = raw[sigpick, first:last]
        if use_reffilter:
            raw_segmentref, times = fltref[:, first:last]
        else:
            raw_segmentref, times = raw[refpick, first:last]

        if not exclude_artifacts or \
           _is_good(raw_segmentsig, infosig['ch_names'], idx_by_typesig, reject, flat=None,
                    ignore_chs=raw.info['bads']):
            sigmean += raw_segmentsig.sum(axis=1)
            refmean += raw_segmentref.sum(axis=1)
            sscovdata += (raw_segmentsig * raw_segmentsig).sum(axis=1)
            srcovdata += np.dot(raw_segmentsig, raw_segmentref.T)
            rrcovdata += np.dot(raw_segmentref, raw_segmentref.T)
            n_samples += raw_segmentsig.shape[1]
        else:
            logger.info("Artefact detected in [%d, %d]" % (first, last))
    if n_samples <= 1:
        raise ValueError('Too few samples to calculate weights')
    sigmean /= n_samples
    refmean /= n_samples
    sscovdata -= n_samples * sigmean[:] * sigmean[:]
    sscovdata /= (n_samples - 1)
    srcovdata -= n_samples * sigmean[:, None] * refmean[None, :]
    srcovdata /= (n_samples - 1)
    rrcovdata -= n_samples * refmean[:, None] * refmean[None, :]
    rrcovdata /= (n_samples - 1)
    sscovinit = np.copy(sscovdata)
    if verbose:
        print ">>> Normalize srcov..."

    rrslope = copy.copy(rrcovdata)
    for iref in xrange(nref):
        dtmp = rrcovdata[iref, iref]
        if dtmp > TINY:
            srcovdata[:, iref] /= dtmp
            rrslope[:, iref] /= dtmp
        else:
            srcovdata[:, iref] = 0.
            rrslope[:, iref] = 0.

    if verbose:
        print ">>> Number of samples used : %d" % n_samples
        tc1 = time.clock()
        tw1 = time.time()
        print ">>> sigrefchn covar-calc took %.1f ms (%.2f s walltime)" % (
            1000. * (tc1 - tct), (tw1 - twt))

    if checkresults:
        if verbose:
            print "########## Calculated initial signal channel covariance:"
            # Calculate initial signal channel covariance:
            # (only used as quality measure)
            print ">>> initl rt(avg sig pwr) = %12.5e" % np.sqrt(
                np.mean(sscovdata))
            for i in xrange(5):
                print ">>> initl signal-rms[%3d] = %12.5e" % (
                    i, np.sqrt(sscovdata.flatten()[i]))
            print ">>>"

    U, s, V = np.linalg.svd(rrslope, full_matrices=True)
    if verbose:
        print ">>> singular values:"
        print s
        print ">>> Applying cutoff for smallest SVs:"

    dtmp = s.max() * SVD_RELCUTOFF
    s *= (abs(s) >= dtmp)
    sinv = [1. / s[k] if s[k] != 0. else 0. for k in xrange(nref)]
    if verbose:
        print ">>> singular values (after cutoff):"
        print s

    stat = np.allclose(rrslope, np.dot(U, np.dot(np.diag(s), V)))
    if verbose:
        print ">>> Testing svd-result: %s" % stat
        if not stat:
            print "    (Maybe due to SV-cutoff?)"

    # Solve for inverse coefficients:
    # Set RRinv.tr=U diag(sinv) V
    RRinv = np.transpose(np.dot(U, np.dot(np.diag(sinv), V)))
    if checkresults:
        stat = np.allclose(np.identity(nref), np.dot(RRinv, rrslope))
        if stat:
            if verbose:
                print ">>> Testing RRinv-result (should be unit-matrix): ok"
        else:
            print ">>> Testing RRinv-result (should be unit-matrix): failed"
            print np.transpose(np.dot(RRinv, rrslope))
            print ">>>"

    if verbose:
        print "########## Calc weight matrix..."

    # weights-matrix will be somewhat larger than necessary,
    # (to simplify indexing in compensation loop):
    weights = np.zeros((raw._data.shape[0], nref))
    for isig in xrange(nsig):
        for iref in xrange(nref):
            weights[sigpick[isig], iref] = np.dot(srcovdata[isig, :],
                                                  RRinv[:, iref])

    if verbose:
        print "########## Compensating signal channels:"
        if complementary_signal:
            print ">>> Caveat: REPLACING signal by compensation signal"

    tct = time.clock()
    twt = time.time()

    # Work on entire data stream:
    for isl in xrange(raw._data.shape[1]):
        slice = np.take(raw._data, [isl], axis=1)
        if use_reffilter:
            refslice = np.take(fltref._data, [isl], axis=1)
            refarr = refslice[:].flatten() - refmean
            # refarr = fltres[:,isl]-refmean
        else:
            refarr = slice[refpick].flatten() - refmean
        subrefarr = np.dot(weights[:], refarr)

        if not complementary_signal:
            raw._data[:, isl] -= subrefarr
        else:
            raw._data[:, isl] = subrefarr

        if (isl % 10000 == 0) and verbose:
            print "\rProcessed slice %6d" % isl

    if verbose:
        print "\nDone."
        tc1 = time.clock()
        tw1 = time.time()
        print ">>> compensation loop took %.1f ms (%.2f s walltime)" % (
            1000. * (tc1 - tct), (tw1 - twt))

    if checkresults:
        if verbose:
            print "########## Calculating final signal channel covariance:"
        # Calculate final signal channel covariance:
        # (only used as quality measure)
        tct = time.clock()
        twt = time.time()
        sigmean = 0
        sscovdata = 0
        n_samples = 0
        for first in range(itmin, itmax, itstep):
            last = first + itstep
            if last >= itmax:
                last = itmax
            raw_segmentsig, times = raw[sigpick, first:last]
            # Artifacts found here will probably differ from pre-noisered artifacts!
            if not exclude_artifacts or \
               _is_good(raw_segmentsig, infosig['ch_names'], idx_by_typesig, reject,
                        flat=None, ignore_chs=raw.info['bads']):
                sigmean += raw_segmentsig.sum(axis=1)
                sscovdata += (raw_segmentsig * raw_segmentsig).sum(axis=1)
                n_samples += raw_segmentsig.shape[1]
        sigmean /= n_samples
        sscovdata -= n_samples * sigmean[:] * sigmean[:]
        sscovdata /= (n_samples - 1)

        if verbose:
            print ">>> no channel got worse: ", np.all(
                np.less_equal(sscovdata, sscovinit))
            print ">>> final rt(avg sig pwr) = %12.5e" % np.sqrt(
                np.mean(sscovdata))
            for i in xrange(5):
                print ">>> final signal-rms[%3d] = %12.5e" % (
                    i, np.sqrt(sscovdata.flatten()[i]))
            tc1 = time.clock()
            tw1 = time.time()
            print ">>> signal covar-calc took %.1f ms (%.2f s walltime)" % (
                1000. * (tc1 - tct), (tw1 - twt))
            print ">>>"

#--- fb update 21.07.2015
    fname_out = jumeg_base.get_fif_name(raw=raw,
                                        postfix=fif_postfix,
                                        extention=fif_extention)

    if save:
        jumeg_base.apply_save_mne_data(raw, fname=fname_out, overwrite=True)

    tc1 = time.clock()
    tw1 = time.time()
    if verbose:
        print ">>> Total run took %.1f ms (%.2f s walltime)" % (1000. *
                                                                (tc1 - tc0),
                                                                (tw1 - tw0))

    return raw, fname_out
示例#3
0
def apply_noise_reducer_data(fname,
                             raw=None,
                             do_run=True,
                             verbose=False,
                             save=True,
                             plot=False,
                             reflp=None,
                             refhp=None,
                             refnotch=None,
                             fif_postfix="nr",
                             fif_extention="-raw.fif",
                             **kwargs):
    '''
    Applies the noise reducer to raw obj data or to fif-file.
            the magic ee once
            fb modified for raw obj support
            imports jumeg_noise_reducer_4raw_data
    '''

    import os

    #--- import noise_reducer and plot_power_spectrum function
    from jumeg.jumeg_4raw_data_noise_reducer import noise_reducer_4raw_data, plot_denoising_4raw_data

    fname_out = None
    nr_done = False

    if do_run:
        raw, fname_raw = jumeg_base.get_raw_obj(fname, raw=raw)
        fname_out = jumeg_base.get_fif_name(raw=raw,
                                            postfix=fif_postfix,
                                            extention=fif_extention,
                                            update_raw_fname=False)

        #--- apply noise reducer for 50 Hz (and harmonics)

        if (reflp or refhp):
            raw, fname_out = noise_reducer_4raw_data(fname,
                                                     raw=raw,
                                                     reflp=reflp,
                                                     refhp=refhp,
                                                     verbose=verbose,
                                                     save=False,
                                                     **kwargs['parameter'])
            kwargs['parameter']['detrending'] = None
            nr_done = True
        if refnotch:
            for refn in refnotch:
                raw, fname_out = noise_reducer_4raw_data(None,
                                                         raw=raw,
                                                         refnotch=refn,
                                                         verbose=verbose,
                                                         save=False,
                                                         **kwargs['parameter'])
                kwargs['parameter']['detrending'] = None
            nr_done = True

        # raw.info['filename'] = fname_out

        if not nr_done:
            return fname_raw, raw

        raw.info['filename'] = fname_out

        if save:
            fname_out = jumeg_base.apply_save_mne_data(raw, fname=fname_out)

        if plot:
            print " --> noise reducer plot power spectrum"

            from distutils.dir_util import mkpath

            p, pdf = os.path.split(fname_raw)

            plot_dir = p + '/plots/'

            mkpath(plot_dir)

            fn_power_spect = plot_dir + pdf[:pdf.rfind('-raw.fif'
                                                       )] + ',denoising'

            plot_denoising_4raw_data([fname_raw, fname_out],
                                     show=False,
                                     fnout=fn_power_spect)

            print "---> noise reducer plot :" + fn_power_spect

    print "---> Done noise reducer: " + fname_out

    return (fname_out, raw)
def apply_noise_reducer_data(fname,raw=None,do_run=True,verbose=False,save=True,plot=False,
                             reflp=None, refhp=None, refnotch=None,fif_postfix="nr",fif_extention="-raw.fif",**kwargs):
    '''
    Applies the noise reducer to raw obj data or to fif-file.
            the magic ee once
            fb modified for raw obj support
            imports jumeg_noise_reducer_4raw_data
    '''

    import os

#--- import noise_reducer and plot_power_spectrum function
    from jumeg.jumeg_4raw_data_noise_reducer import noise_reducer_4raw_data, plot_denoising_4raw_data

    fname_out = None
    nr_done   = False
    
    if do_run :  
       raw,fname_raw = jumeg_base.get_raw_obj(fname,raw=raw)
       fname_out = jumeg_base.get_fif_name(raw=raw,postfix=fif_postfix,extention=fif_extention,update_raw_fname=False)
     
#--- apply noise reducer for 50 Hz (and harmonics)
     
       if (reflp or refhp):
          raw,fname_out = noise_reducer_4raw_data(fname,raw=raw,reflp=reflp,refhp=refhp,verbose=verbose,save=False,**kwargs['parameter'])
          kwargs['parameter']['detrending'] = None
          nr_done = True
       if refnotch:
          for refn in refnotch:
              raw,fname_out = noise_reducer_4raw_data(None,raw=raw,refnotch=refn,verbose=verbose,save=False,**kwargs['parameter'])
              kwargs['parameter']['detrending'] = None
          nr_done = True
  
     
       # raw.info['filename'] = fname_out
       
       if not nr_done :
          return fname_raw,raw
  
       raw.info['filename'] = fname_out
       
       if save:
          fname_out = jumeg_base.apply_save_mne_data(raw,fname=fname_out)

       if plot:
          print " --> noise reducer plot power spectrum"

          from distutils.dir_util import mkpath

          p,pdf = os.path.split(fname_raw)

          plot_dir = p+ '/plots/'

          mkpath(plot_dir)

          fn_power_spect = plot_dir + pdf[:pdf.rfind('-raw.fif') ]+ ',denoising'

          plot_denoising_4raw_data([fname_raw,fname_out],show=False,fnout=fn_power_spect)

          print"---> noise reducer plot :"  + fn_power_spect

    print "---> Done noise reducer: "+ fname_out

    return (fname_out,raw)
def noise_reducer_4raw_data(fname_raw,raw=None,signals=[],noiseref=[],detrending=None,
                  tmin=None,tmax=None,reflp=None,refhp=None,refnotch=None,
                  exclude_artifacts=True,checkresults=True,
                  fif_extention="-raw.fif",fif_postfix="nr",                        
                  reject={'grad':4000e-13,'mag':4e-12,'eeg':40e-6,'eog':250e-6},
                  complementary_signal=False,fnout=None,verbose=False,save=True):

    """Apply noise reduction to signal channels using reference channels.
        
       !!! ONLY ONE RAW Obj Interface Version FB !!!
           
    Parameters
    ----------
    fname_raw : rawfile name

    raw     : fif raw object

    signals : list of string
              List of channels to compensate using noiseref.
              If empty use the meg signal channels.
    noiseref : list of string | str
              List of channels to use as noise reference.
              If empty use the magnetic reference channsls (default).
    signals and noiseref may contain regexp, which are resolved
    using mne.pick_channels_regexp(). All other channels are copied.
    tmin : lower latency bound for weight-calc [start of trace]
    tmax : upper latency bound for weight-calc [ end  of trace]
           Weights are calc'd for (tmin,tmax), but applied to entire data set
    refhp : high-pass frequency for reference signal filter [None]
    reflp :  low-pass frequency for reference signal filter [None]
            reflp < refhp: band-stop filter
            reflp > refhp: band-pass filter
            reflp is not None, refhp is None: low-pass filter
            reflp is None, refhp is not None: high-pass filter
    refnotch : (base) notch frequency for reference signal filter [None]
               use raw(ref)-notched(ref) as reference signal
    exclude_artifacts: filter signal-channels thru _is_good() [True]
                       (parameters are at present hard-coded!)
    complementary_signal : replaced signal by traces that would be subtracted [False]
                           (can be useful for debugging)
    checkresults : boolean to control internal checks and overall success [True]

    reject =  dict for rejection threshold 
              units:
              grad:    T / m (gradiometers)
              mag:     T (magnetometers)
              eeg/eog: uV (EEG channels)
              default=>{'grad':4000e-13,'mag':4e-12,'eeg':40e-6,'eog':250e-6}
              
    save : save data to fif file

    Outputfile:
    -------
    <wawa>,nr-raw.fif for input <wawa>-raw.fif

    Returns
    -------
    TBD

    Bugs
    ----
    - artifact checking is incomplete (and with arb. window of tstep=0.2s)
    - no accounting of channels used as signal/reference
    - non existing input file handled ungracefully
    """

    tc0 = time.clock()
    tw0 = time.time()

    if type(complementary_signal) != bool:
        raise ValueError("Argument complementary_signal must be of type bool")

    raw,fname_raw = jumeg_base.get_raw_obj(fname_raw,raw=raw)
    
    
    if detrending:
       raw = perform_detrending(None,raw=raw, save=False)
    
    tc1 = time.clock()
    tw1 = time.time()

    if verbose:
       print ">>> loading raw data took %.1f ms (%.2f s walltime)" % (1000. * (tc1 - tc0), (tw1 - tw0))

    # Time window selection
    # weights are calc'd based on [tmin,tmax], but applied to the entire data set.
    # tstep is used in artifact detection
    # tmin,tmax variables must not be changed here!
    if tmin is None:
        itmin = 0
    else:
        itmin = int(floor(tmin * raw.info['sfreq']))
    if tmax is None:
        itmax = raw.last_samp
    else:
        itmax = int(ceil(tmax * raw.info['sfreq']))

    if itmax - itmin < 2:
        raise ValueError("Time-window for noise compensation empty or too short")

    if verbose:
        print ">>> Set time-range to [%7.3f,%7.3f]" % \
              (raw.index_as_time(itmin)[0], raw.index_as_time(itmax)[0])

    if signals is None or len(signals) == 0:
        sigpick = jumeg_base.pick_meg_nobads(raw)
    else:
        sigpick = channel_indices_from_list(raw.info['ch_names'][:], signals,
                                            raw.info.get('bads'))
    nsig = len(sigpick)
    if nsig == 0:
        raise ValueError("No channel selected for noise compensation")

    if noiseref is None or len(noiseref) == 0:
        # References are not limited to 4D ref-chans, but can be anything,
        # incl. ECG or powerline monitor.
        if verbose:
            print ">>> Using all refchans."
            
        refexclude = "bads"      
        refpick = jumeg_base.pick_ref_nobads(raw)
    else:
        refpick = channel_indices_from_list(raw.info['ch_names'][:], noiseref,
                                            raw.info.get('bads'))
    nref = len(refpick)
    if nref == 0:
        raise ValueError("No channel selected as noise reference")

    if verbose:
        print ">>> sigpick: %3d chans, refpick: %3d chans" % (nsig, nref)

    if reflp is None and refhp is None and refnotch is None:
        use_reffilter = False
        use_refantinotch = False
    else:
        use_reffilter = True
        if verbose:
            print "########## Filter reference channels:"

        use_refantinotch = False
        if refnotch is not None:
            if reflp is None and reflp is None:
                use_refantinotch = True
                freqlast = np.min([5.01 * refnotch, 0.5 * raw.info['sfreq']])
                if verbose:
                    print ">>> notches at freq %.1f and harmonics below %.1f" % (refnotch, freqlast)
            else:
                raise ValueError("Cannot specify notch- and high-/low-pass"
                                 "reference filter together")
        else:
            if verbose:
                if reflp is not None:
                    print ">>>  low-pass with cutoff-freq %.1f" % reflp
                if refhp is not None:
                    print ">>> high-pass with cutoff-freq %.1f" % refhp

        # Adapt followg drop-chans cmd to use 'all-but-refpick'
        droplist = [raw.info['ch_names'][k] for k in xrange(raw.info['nchan']) if not k in refpick]
        tct = time.clock()
        twt = time.time()
        fltref = raw.drop_channels(droplist, copy=True)
        if use_refantinotch:
            rawref = raw.drop_channels(droplist, copy=True)
            freqlast = np.min([5.01 * refnotch, 0.5 * raw.info['sfreq']])
            fltref.notch_filter(np.arange(refnotch, freqlast, refnotch),
                                picks=np.array(xrange(nref)), method='iir')
            fltref._data = (rawref._data - fltref._data)
        else:
            fltref.filter(refhp, reflp, picks=np.array(xrange(nref)), method='iir')
        tc1 = time.clock()
        tw1 = time.time()
        if verbose:
            print ">>> filtering ref-chans  took %.1f ms (%.2f s walltime)" % (1000. * (tc1 - tct), (tw1 - twt))

    if verbose:
        print "########## Calculating sig-ref/ref-ref-channel covariances:"
    # Calculate sig-ref/ref-ref-channel covariance:
    # (there is no need to calc inter-signal-chan cov,
    #  but there seems to be no appropriat fct available)
    # Here we copy the idea from compute_raw_data_covariance()
    # and truncate it as appropriate.
    tct = time.clock()
    twt = time.time()
    # The following reject and infosig entries are only
    # used in _is_good-calls.
    # _is_good() from mne-0.9.git-py2.7.egg/mne/epochs.py seems to
    # ignore ref-channels (not covered by dict) and checks individual
    # data segments - artifacts across a buffer boundary are not found.
    
    #--- !!! FB put to kwargs    
    
    #reject = dict(grad=4000e-13, # T / m (gradiometers)
    #              mag=4e-12,     # T (magnetometers)
    #              eeg=40e-6,     # uV (EEG channels)
    #              eog=250e-6)    # uV (EOG channels)

    infosig = copy.copy(raw.info)
    infosig['chs'] = [raw.info['chs'][k] for k in sigpick]
    infosig['ch_names'] = [raw.info['ch_names'][k] for k in sigpick]
    infosig['nchan'] = len(sigpick)
    idx_by_typesig = channel_indices_by_type(infosig)

    # Read data in chunks:
    tstep = 0.2
    itstep = int(ceil(tstep * raw.info['sfreq']))
    sigmean = 0
    refmean = 0
    sscovdata = 0
    srcovdata = 0
    rrcovdata = 0
    n_samples = 0

    for first in range(itmin, itmax, itstep):
        last = first + itstep
        if last >= itmax:
            last = itmax
        raw_segmentsig, times = raw[sigpick, first:last]
        if use_reffilter:
            raw_segmentref, times = fltref[:, first:last]
        else:
            raw_segmentref, times = raw[refpick, first:last]

        if not exclude_artifacts or \
           _is_good(raw_segmentsig, infosig['ch_names'], idx_by_typesig, reject, flat=None,
                    ignore_chs=raw.info['bads']):
            sigmean += raw_segmentsig.sum(axis=1)
            refmean += raw_segmentref.sum(axis=1)
            sscovdata += (raw_segmentsig * raw_segmentsig).sum(axis=1)
            srcovdata += np.dot(raw_segmentsig, raw_segmentref.T)
            rrcovdata += np.dot(raw_segmentref, raw_segmentref.T)
            n_samples += raw_segmentsig.shape[1]
        else:
            logger.info("Artefact detected in [%d, %d]" % (first, last))
    if n_samples <= 1:
        raise ValueError('Too few samples to calculate weights')
    sigmean /= n_samples
    refmean /= n_samples
    sscovdata -= n_samples * sigmean[:] * sigmean[:]
    sscovdata /= (n_samples - 1)
    srcovdata -= n_samples * sigmean[:, None] * refmean[None, :]
    srcovdata /= (n_samples - 1)
    rrcovdata -= n_samples * refmean[:, None] * refmean[None, :]
    rrcovdata /= (n_samples - 1)
    sscovinit = np.copy(sscovdata)
    if verbose:
        print ">>> Normalize srcov..."

    rrslope = copy.copy(rrcovdata)
    for iref in xrange(nref):
        dtmp = rrcovdata[iref, iref]
        if dtmp > TINY:
            srcovdata[:, iref] /= dtmp
            rrslope[:, iref] /= dtmp
        else:
            srcovdata[:, iref] = 0.
            rrslope[:, iref] = 0.

    if verbose:
        print ">>> Number of samples used : %d" % n_samples
        tc1 = time.clock()
        tw1 = time.time()
        print ">>> sigrefchn covar-calc took %.1f ms (%.2f s walltime)" % (1000. * (tc1 - tct), (tw1 - twt))

    if checkresults:
        if verbose:
            print "########## Calculated initial signal channel covariance:"
            # Calculate initial signal channel covariance:
            # (only used as quality measure)
            print ">>> initl rt(avg sig pwr) = %12.5e" % np.sqrt(np.mean(sscovdata))
            for i in xrange(5):
                print ">>> initl signal-rms[%3d] = %12.5e" % (i, np.sqrt(sscovdata.flatten()[i]))
            print ">>>"

    U, s, V = np.linalg.svd(rrslope, full_matrices=True)
    if verbose:
        print ">>> singular values:"
        print s
        print ">>> Applying cutoff for smallest SVs:"

    dtmp = s.max() * SVD_RELCUTOFF
    s *= (abs(s) >= dtmp)
    sinv = [1. / s[k] if s[k] != 0. else 0. for k in xrange(nref)]
    if verbose:
        print ">>> singular values (after cutoff):"
        print s

    stat = np.allclose(rrslope, np.dot(U, np.dot(np.diag(s), V)))
    if verbose:
        print ">>> Testing svd-result: %s" % stat
        if not stat:
            print "    (Maybe due to SV-cutoff?)"

    # Solve for inverse coefficients:
    # Set RRinv.tr=U diag(sinv) V
    RRinv = np.transpose(np.dot(U, np.dot(np.diag(sinv), V)))
    if checkresults:
        stat = np.allclose(np.identity(nref), np.dot(RRinv, rrslope))
        if stat:
            if verbose:
                print ">>> Testing RRinv-result (should be unit-matrix): ok"
        else:
            print ">>> Testing RRinv-result (should be unit-matrix): failed"
            print np.transpose(np.dot(RRinv, rrslope))
            print ">>>"

    if verbose:
        print "########## Calc weight matrix..."

    # weights-matrix will be somewhat larger than necessary,
    # (to simplify indexing in compensation loop):
    weights = np.zeros((raw._data.shape[0], nref))
    for isig in xrange(nsig):
        for iref in xrange(nref):
            weights[sigpick[isig],iref] = np.dot(srcovdata[isig,:], RRinv[:,iref])

    if verbose:
        print "########## Compensating signal channels:"
        if complementary_signal:
            print ">>> Caveat: REPLACING signal by compensation signal"

    tct = time.clock()
    twt = time.time()

    # Work on entire data stream:
    for isl in xrange(raw._data.shape[1]):
        slice = np.take(raw._data, [isl], axis=1)
        if use_reffilter:
            refslice = np.take(fltref._data, [isl], axis=1)
            refarr = refslice[:].flatten() - refmean
            # refarr = fltres[:,isl]-refmean
        else:
            refarr = slice[refpick].flatten() - refmean
        subrefarr = np.dot(weights[:], refarr)

        if not complementary_signal:
            raw._data[:, isl] -= subrefarr
        else:
            raw._data[:, isl] = subrefarr

        if (isl % 10000 == 0) and verbose:
            print "\rProcessed slice %6d" % isl

    if verbose:
        print "\nDone."
        tc1 = time.clock()
        tw1 = time.time()
        print ">>> compensation loop took %.1f ms (%.2f s walltime)" % (1000. * (tc1 - tct), (tw1 - twt))

    if checkresults:
        if verbose:
            print "########## Calculating final signal channel covariance:"
        # Calculate final signal channel covariance:
        # (only used as quality measure)
        tct = time.clock()
        twt = time.time()
        sigmean = 0
        sscovdata = 0
        n_samples = 0
        for first in range(itmin, itmax, itstep):
            last = first + itstep
            if last >= itmax:
                last = itmax
            raw_segmentsig, times = raw[sigpick, first:last]
            # Artifacts found here will probably differ from pre-noisered artifacts!
            if not exclude_artifacts or \
               _is_good(raw_segmentsig, infosig['ch_names'], idx_by_typesig, reject,
                        flat=None, ignore_chs=raw.info['bads']):
                sigmean += raw_segmentsig.sum(axis=1)
                sscovdata += (raw_segmentsig * raw_segmentsig).sum(axis=1)
                n_samples += raw_segmentsig.shape[1]
        sigmean /= n_samples
        sscovdata -= n_samples * sigmean[:] * sigmean[:]
        sscovdata /= (n_samples - 1)
        
        if verbose:
            print ">>> no channel got worse: ", np.all(np.less_equal(sscovdata, sscovinit))
            print ">>> final rt(avg sig pwr) = %12.5e" % np.sqrt(np.mean(sscovdata))
            for i in xrange(5):
                print ">>> final signal-rms[%3d] = %12.5e" % (i, np.sqrt(sscovdata.flatten()[i]))
            tc1 = time.clock()
            tw1 = time.time()
            print ">>> signal covar-calc took %.1f ms (%.2f s walltime)" % (1000. * (tc1 - tct), (tw1 - twt))
            print ">>>"

   #--- fb update 21.07.2015     
    fname_out = jumeg_base.get_fif_name(raw=raw,postfix=fif_postfix,extention=fif_extention)                       
      
    if save:    
       jumeg_base.apply_save_mne_data(raw,fname=fname_out,overwrite=True)
     
             
    tc1 = time.clock()
    tw1 = time.time()
    if verbose:
       print ">>> Total run took %.1f ms (%.2f s walltime)" % (1000. * (tc1 - tc0), (tw1 - tw0))
        
    return raw,fname_out