示例#1
0
def testConvexHull2D():
    h = pyopenms.ConvexHull2D()

    points = numpy.arange(10.0, dtype=numpy.float32).reshape(-1, 2)

    h.setHullPoints(points)
    p = h.getHullPoints()
    assert numpy.linalg.norm(p - points) < 1e-6

    h.expandToBoundingBox()
    hullp = h.getHullPoints()
    assert set(hullp[:,0]) == set((0.0, 8.0))
    assert set(hullp[:,1]) == set((1.0, 9.0))

    box = h.getBoundingBox()
    assert box.minPosition() == [ 0.0, 1.0]
    assert box.maxPosition() == [ 8.0, 9.0]

    h.addPoint([-10.0, -10.0])
    box = h.getBoundingBox()
    assert box.minPosition() == [ -10.0, -10.0]
    assert box.maxPosition() == [ 8.0, 9.0]
    h.expandToBoundingBox()
    hullp = h.getHullPoints()
    assert set(hullp[:,0]) == set((-10.0, 8.0))
    assert set(hullp[:,1]) == set((-10.0, 9.0))
    box = h.getBoundingBox()
    assert box.minPosition() == [ -10.0, -10.0]
    assert box.maxPosition() == [ 8.0, 9.0]
示例#2
0
def test_convex_hull_1():
    ch = pyopenms.ConvexHull2D()

    points = [[1.0, 1.0], [2.0, 1.0], [1.0, 2.0], [2.0, 2.0]]
    for p in points:
        ch.addPoint(p)

    assert ch.encloses([1.5, 1.5])
    assert not ch.encloses([.5, 1.5])

    hp = ch.getHullPoints()
    # order may change, so we use sort here:
    assert sorted(hp.tolist()) == sorted(points)

    ch.setHullPoints(hp)
    hp = ch.getHullPoints()
    # order may change, so we use sorted here:
    assert sorted(hp.tolist()) == sorted(points)

    ch.addPoints(hp + 1.0)
    ch.addPoints(hp)
    hp = ch.getHullPoints()
    assert hp.shape == (6, 2)

    bb = ch.getBoundingBox()
    assert bb.minPosition() == [1.0, 1.0]
    assert bb.maxPosition() == [3.0, 3.0]
示例#3
0
def test_convex_hull_0():
    ch = pyopenms.ConvexHull2D()
示例#4
0
def main(options):
    starttime = time.time()
    tolerance = float(options.tolerance)
    precursorshift = float(options.precursorshift)
    mswindow = float(options.mswindow)
    rtwindow = float(options.rtwindow)

    # load file
    timed("loading experiment", starttime)
    exp = glyxtoolms.lib.openOpenMSExperiment(options.infile)
    # assure sorted spectra
    exp.sortSpectra()
    timed("sort spectra", starttime)
    ms1, ms2 = sortSpectra(exp)

    links = []
    noresult = 0

    timed("finding precursors " + str(len(ms2)), starttime)
    for mz, spec2, spec1 in ms2:
        charge = spec2.getPrecursors()[0].getCharge()
        if charge == 0:
            charge = 1
        peaks, results = findMonoIsotopicPeak(mz, charge, spec1, tolerance,
                                              precursorshift, mswindow)
        if len(results) == 0:
            noresult += 1
            continue

        best = min(results, key=lambda r: r["mass"] * r["error"] / r["sum"]**2)
        rt = spec2.getRT()
        link = Link(rt, best)
        link.rt1 = spec1.getRT()
        link.nativeId = spec1.getNativeID()
        link.peaks = peaks
        links.append(link)

    print "could not find suitable starting pattern for ", noresult, "spectra from ", len(
        ms2)
    timed("group precursors", starttime)
    # group precursors
    for l1 in links:
        for l2 in links:
            if l1.charge != l2.charge:
                continue
            if abs(l1.mz - l2.mz) > tolerance:
                continue
            if abs(l1.rt - l2.rt) > rtwindow:
                continue
            l1.near.add(l2)
    timed("group into features", starttime)
    # group into features
    features = []
    while True:
        # find link without feature
        working = set()
        for link in links:
            if link.feature == None:
                working.add(link)
                break
        if len(working) == 0:
            break
        feature = Feature()
        features.append(feature)
        while len(working) > 0:
            current = working.pop()
            current.feature = feature
            feature.ms2.append(current)
            for link in current.near:
                if link.feature == None:
                    working.add(link)

    timed("calculate precursor positions", starttime)
    # calculate mz and charge of feature
    for feature in features:
        feature.mz = sum([l.mz for l in feature.ms2]) / len(feature.ms2)
        feature.charge = feature.ms2[0].charge
        # get lowest error
        feature.error = min([l.result["error"] for l in feature.ms2])
        feature.extendRTDomain(ms1, tolerance)
        # calculate dimensions
        masses = [l.result["x"][-1] for l in feature.ms2]
        feature.mzLow = feature.mz
        feature.mzHigh = max(masses)

    timed("merge features", starttime)
    # check features against each other
    # remove feature if mzLow is within other feature and rtLow and rtHigh within too
    todelete = set()
    for f1 in features:
        for f2 in features:
            if f1 == f2:
                continue
            if abs(f1.mz - f2.mz) > tolerance:
                continue
            if not (f1.mzLow <= f2.mzLow <= f1.mzHigh):
                continue
            if not (f1.rtLow <= f2.rtLow <= f1.rtHigh):
                continue
            if not (f1.rtLow <= f2.rtHigh <= f1.rtHigh):
                continue
            todelete.add(f2)
    for f in todelete:
        features.remove(f)

    newfeatures = set()
    # merge features
    for f1 in features:
        if f1.rtHigh == 0.0:
            print "zero", "f1", [ms.rt for ms in f1.ms2]
        for f2 in features:
            if f1 == f2:
                continue
            if abs(f1.mzLow - f2.mzLow) > tolerance:
                continue
            if f1.charge != f2.charge:
                continue
            if not ((f1.rtLow <= f2.rtLow <= f1.rtHigh)
                    or abs(f2.rtLow - f1.rtHigh) < 30):
                continue
            todelete.add(f1)
            todelete.add(f2)

            # create new feature
            newf = Feature()
            newf.error = min((f1.error, f2.error))
            newf.mz = min((f1.mz, f2.mz))
            newf.mzLow = min((f1.mzLow, f2.mzLow))
            newf.mzHigh = max((f1.mzHigh, f2.mzHigh))
            newf.rtLow = min((f1.rtLow, f2.rtLow))
            newf.rtHigh = max((f1.rtHigh, f2.rtHigh))
            if newf.rtHigh == 0.0:
                print "zero", "newf"
            newf.ms2 = sorted(set(f1.ms2).union(set(f2.ms2)),
                              key=lambda ms: ms.rt)
            newf.rt = (f1.rt + f2.rt) / 2.0
            newfeatures.add(newf)

    features += list(newfeatures)

    timed("write featuremap", starttime)
    fm = pyopenms.FeatureMap()
    N = 0
    for feature in features:
        # calc bounding boxes from pattern
        f = pyopenms.Feature()
        f.ensureUniqueId()
        f.setRT(feature.rt)
        f.setMZ(feature.mz)
        f.setCharge(feature.charge)
        hulls = []
        sumIntensity = 0
        for i in feature.pattern:
            pattern = feature.pattern[i]
            minRT = feature.rtLow - 1  # eliminate rounding error by adding a rt tolerance
            maxRT = feature.rtHigh + 1
            #minRT = min([p[0] for p in pattern])
            #maxRT = max([p[0] for p in pattern])
            minMZ = min([p[1] for p in pattern]) - tolerance
            maxMZ = max([p[1] for p in pattern]) + tolerance
            sumIntensity += sum([p[2] for p in pattern])
            h = pyopenms.ConvexHull2D()
            h.addPoint([minRT, minMZ])
            h.addPoint([maxRT, minMZ])
            h.addPoint([maxRT, maxMZ])
            h.addPoint([minRT, maxMZ])
            hulls.append(h)
        f.setConvexHulls(hulls)
        f.getConvexHull().expandToBoundingBox()
        f.setIntensity(sumIntensity)
        f.setOverallQuality(feature.error)

        # check if boundingbox is fullfilles
        h = f.getConvexHull()
        b = h.getBoundingBox()
        minRT, minMZ = b.minPosition()
        maxRT, maxMZ = b.maxPosition()

        if sumIntensity == 0:
            N += 1
            continue
        if charge == 0:
            N += 1
            continue
        fm.push_back(f)
    print "ignoring ", N, " features that have no peaks or a charge of 0"
    fxml = pyopenms.FeatureXMLFile()
    fxml.store(options.outfile, fm)