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]
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]
def test_convex_hull_0(): ch = pyopenms.ConvexHull2D()
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)