Subtract background from measurements.

    Inputs:
        samplename: the name of the sample
        bgname: the name of the background measurements. Alternatively, it can
            be a numeric value (float or ErrorValue), which will be subtracted.
            If None, this constant will be determined by integrating the
            scattering curve in the range given by qrange.
        factor: the background curve will be multiplied by this
        distance: if None, do the subtraction for all sample-to-detector distances.
            Otherwise give here the value of the sample-to-detector distance.
        qrange: a tuple (qmin, qmax)
        disttolerance: the tolerance in which two distances are considered
            equal.
        subname: the sample name of the background-corrected curve. The default
            is samplename + '-' + bgname

def subtract_bg(samplename, bgname, factor=1, distance=None, disttolerance=2,
                subname=None, qrange=(), graph_extension='png', graph_dpi=80):
    """Subtract background from measurements.

    Inputs:
        samplename: the name of the sample
        bgname: the name of the background measurements. Alternatively, it can
            be a numeric value (float or ErrorValue), which will be subtracted.
            If None, this constant will be determined by integrating the
            scattering curve in the range given by qrange.
        factor: the background curve will be multiplied by this
        distance: if None, do the subtraction for all sample-to-detector distances.
            Otherwise give here the value of the sample-to-detector distance.
        qrange: a tuple (qmin, qmax)
        disttolerance: the tolerance in which two distances are considered
            equal.
        subname: the sample name of the background-corrected curve. The default
            is samplename + '-' + bgname
    """
    ip = get_ipython()
    data1d = ip.user_ns['_data1d']
    data2d = ip.user_ns['_data2d']
    if 'subtractedsamplenames' not in ip.user_ns:
        ip.user_ns['subtractedsamplenames'] = set()
    subtractedsamplenames = ip.user_ns['subtractedsamplenames']
    if subname is None:
        if isinstance(bgname, str):
            subname = samplename + '-' + bgname
        else:
            subname = samplename + '-const'
    if distance is None:
        dists = data1d[samplename]
    else:
        dists = [d for d in data1d[samplename] if abs(d - distance) < disttolerance]
    for dist in dists:
        if isinstance(bgname, str):
            if not disttolerance:
                if dist not in data1d[bgname]:
                    print(
                        'Warning: Missing distance %g for background measurement (samplename: %s, background samplename: %s)' % (
                            dist, samplename, bgname))
                    continue
                else:
                    bgdist = dist
            else:
                bgdist = sorted([(d, r) for (d, r) in [(d, np.abs(d - dist)) for d in list(data1d[bgname].keys())] if
                                 r <= disttolerance], key=lambda x: x[1])[0][0]
        if subname not in data1d:
            data1d[subname] = {}
        if subname not in data2d:
            data2d[subname] = {}
        if subname not in ip.user_ns['_headers_sample']:
            ip.user_ns['_headers_sample'][subname] = {}
        data1_s = data1d[samplename][dist]
        data2_s = data2d[samplename][dist]
        if isinstance(bgname, str):
            data1_bg = data1d[bgname][bgdist]
            data2_bg = data2d[bgname][bgdist]
            if factor is None:
                factor = data1_s.trim(*qrange).momentum(0) / data1_bg.trim(*qrange).momentum(0)
        elif bgname is None:
            data1_bg = data1_s.trim(*qrange).momentum(0)
            data2_bg = data1_bg
        else:
            data1_bg = bgname
            data2_bg = bgname
        if factor is None:
            factor = 1
        data1d[subname][dist] = data1_s - factor * data1_bg
        data2d[subname][dist] = data2_s - factor * data2_bg
        data1d[subname][dist].save(
            os.path.join(ip.user_ns['saveto_dir'], subname + '_' + ('%.2f' % dist).replace('.', '_') + '.txt'))
        ip.user_ns['_headers_sample'][subname][dist] = ip.user_ns['_headers_sample'][samplename][
            dist]  # ugly hack, I have no better idea.
        plt.figure()
        plotsascurve(samplename, dist=dist)
        if isinstance(bgname, str):
            plotsascurve(bgname, dist=dist, factor=factor)
        plotsascurve(subname, dist=dist)
        plt.savefig(os.path.join(ip.user_ns['auximages_dir'],
                                 'subtractbg_' + samplename + '.' + graph_extension),
                    dpi=graph_dpi)

        subtractedsamplenames.add(subname)