def handle_compressed_frame(allmz, allint, allim, mslevel, rtime, center, width): mz = np.concatenate(allmz) intens = np.concatenate(allint) ims = np.concatenate(allim) fda = pyopenms.FloatDataArray() fda.setName("Ion Mobility") fda.resize(len(mz)) for k, val in enumerate(ims): fda[k] = val sframe = pyopenms.MSSpectrum() sframe.setMSLevel(mslevel) sframe.setRT(rtime) sframe.setFloatDataArrays([fda]) p = pyopenms.Precursor() if mslevel == 2: p.setMZ(center) p.setIsolationWindowUpperOffset(width / 2.0) p.setIsolationWindowLowerOffset(width / 2.0) sframe.setPrecursors([p]) sframe.set_peaks((mz, intens)) sframe.sortByPosition() return sframe
def four_d_spectrum_to_experiment(spec): """Function that converts a 4D spectrum object which contains retention time, ion mobility, mass to charge, and intensity data, into a new experiment where the ion mobility becomes the retention time of each of its new spectra and vice versa. Args: spec (MSSpectrum): An OpenMS MSSpectrum object. Returns: MSExperiment: A new MSExperiment where each MSSpectrum object is a 3D spectrum from the original where the retention time and ion mobility has been swapped. """ ion_mobility_to_peaks = zip(spec.getFloatDataArrays()[0], *spec.get_peaks()) new_exp = ms.MSExperiment() new_mz, new_int = [], [] curr_im = None for im, mz, intensity in sorted(ion_mobility_to_peaks, key=lambda x: (x[0], x[1], x[2])): if im != curr_im: if curr_im: new_spec = ms.MSSpectrum() new_spec.setRT(curr_im) new_spec.set_peaks((new_mz, new_int)) rt_fda = ms.FloatDataArray() for i in new_mz: rt_fda.push_back(spec.getRT()) new_spec.setFloatDataArrays([rt_fda]) new_exp.addSpectrum(new_spec) new_mz, new_int = [], [] curr_im = im new_mz.append(mz) new_int.append(intensity) return new_exp
def bin_spectrum(self, spec: ms.MSSpectrum) -> None: """Bins a single spectrum in two passes. Keyword arguments: spec: the spectrum to bin """ points = util.get_spectrum_points(spec) points.sort(key=itemgetter(3)) # Ascending IM temp_bins = [[], [[]]] # 2D spectra new_bins = [[], [[]]] # Final 1D spectra for i in range(self.num_bins): for j in range(2): temp_bins[j].append([]) new_bins[j].append([]) for i in range(len(points)): # Assign points to bins bin_idx = int((points[i][3] - self.im_start) / self.bin_size) if bin_idx >= self.num_bins: bin_idx = self.num_bins - 1 temp_bins[0][bin_idx].append(points[i]) bin_idx = int((points[i][3] - self.im_offset) / self.bin_size) + 1 if points[i][3] < self.im_offset: bin_idx = 0 elif bin_idx > self.num_bins: bin_idx = self.num_bins temp_bins[1][bin_idx].append(points[i]) for i in range(self.num_bins): # First pass if len(temp_bins[0][i]) == 0: continue temp_bins[0][i].sort(key=itemgetter(1)) # Ascending m/z mz_start, curr_mz = 0, temp_bins[0][i][0][1] running_intensity = 0 for j in range(len(temp_bins[0][i])): if self.within_epsilon(curr_mz, temp_bins[0][i][j][1]): running_intensity += temp_bins[0][i][j][2] else: # Reached a new m/z slice point = list( temp_bins[0][i][mz_start]) # Prevents aliasing point[2] = running_intensity new_bins[0][i].append(point) mz_start, curr_mz = j, temp_bins[0][i][j][1] running_intensity = temp_bins[0][i][j][2] point = list( temp_bins[0][i][mz_start]) # Take care of the last slice point[2] = running_intensity new_bins[0][i].append(point) transpose = list(zip(*new_bins[0][i])) new_spec = ms.MSSpectrum() # The final binned spectrum im_fda = ms.FloatDataArray() for im in transpose[3]: im_fda.push_back(im) new_spec.setRT(spec.getRT()) new_spec.set_peaks((list(transpose[1]), list(transpose[2]))) new_spec.setFloatDataArrays([im_fda]) self.exps[0][i].addSpectrum(new_spec) for i in range(self.num_bins + 1): # Second pass if len(temp_bins[1][i]) == 0: continue temp_bins[1][i].sort(key=itemgetter(1)) mz_start, curr_mz = 0, temp_bins[1][i][0][1] running_intensity = 0 for j in range(len(temp_bins[1][i])): if self.within_epsilon(curr_mz, temp_bins[1][i][j][1]): running_intensity += temp_bins[1][i][j][2] else: point = list(temp_bins[1][i][mz_start]) point[2] = running_intensity new_bins[1][i].append(point) mz_start, curr_mz = j, temp_bins[1][i][j][1] running_intensity = temp_bins[1][i][j][2] point = list(temp_bins[1][i][mz_start]) point[2] = running_intensity new_bins[1][i].append(point) transpose = list(zip(*new_bins[1][i])) new_spec = ms.MSSpectrum() im_fda = ms.FloatDataArray() for im in transpose[3]: im_fda.push_back(im) new_spec.setRT(spec.getRT()) new_spec.set_peaks((list(transpose[1]), list(transpose[2]))) new_spec.setFloatDataArrays([im_fda]) self.exps[1][i].addSpectrum(new_spec)
def store_frame(frame_id, td, conn, exp, verbose=False, compressFrame=True): """ Store a single frame as an individual mzML file Note that there are two ways to store the data: (i) Multiple spectra per frame (for visualization), compressFrame is False. This is the easiest way to visualize and process the data but involves a few hacks, namely storing the IM axis as the RT of each spectrum. (ii) One spectrum per frame, compressFrame is True. This puts all peaks into a single spectrum (while storing the IM data in an extra array). This is more efficient for storage and allows analysis that is ignorant of the IM dimension. """ # Get a projected mass spectrum: q = conn.execute("SELECT NumScans, Time, Polarity, MsMsType FROM Frames WHERE Id={0}".format(frame_id)) tmp = q.fetchone() num_scans = tmp[0] time = tmp[1] pol = tmp[2] msms = int(tmp[3]) center = -1 width = -1 mslevel = 1 if msms == 2: q = conn.execute("SELECT TriggerMass, IsolationWidth, PrecursorCharge, CollisionEnergy FROM FrameMsMsInfo WHERE Frame={0}".format(frame_id)) tmp = q.fetchone() center = float(tmp[0]) width = float(tmp[1]) mslevel = 2 if verbose: print "mslevel", mslevel, msms # Get the mapping of the ion mobility axis scan_number_axis = np.arange(num_scans, dtype=np.float64) ook0_axis = td.scanNumToOneOverK0(frame_id, scan_number_axis) allmz = [] allint = [] allim = [] # Traverse in reversed order to get low ion mobilities first for k, scan in reversed(list(enumerate(td.readScans(frame_id, 0, num_scans)))): index = np.array(scan[0], dtype=np.float64) mz = td.indexToMz(frame_id, index) intens = scan[1] drift_time = ook0_axis [k] if compressFrame: allmz.append(mz) allint.append(intens) allim.append([drift_time for k in mz]) continue # Store data in OpenMS Spectrum file -> each TOF push is an individual # spectrum and we store the ion mobility in the precursor. The frame # can be reconstructed by grouping all spectra with the same RT. s = pyopenms.MSSpectrum() s.setMSLevel(mslevel) s.set_peaks( (mz, intens) ) s.setRT(time) p = pyopenms.Precursor() p.setDriftTime(drift_time) if msms == 2: p.setMZ(center) p.setIsolationWindowUpperOffset(width / 2.0) p.setIsolationWindowLowerOffset(width / 2.0) s.setPrecursors([p]) exp.consumeSpectrum(s) if compressFrame: mz = np.concatenate(allmz) intens = np.concatenate(allint) ims = np.concatenate(allim) # print " leeen", len(mz), len(intens) fda = pyopenms.FloatDataArray() fda.setName("Ion Mobility") fda.resize(len(mz)) for k,val in enumerate(ims): fda[k] = val sframe = pyopenms.MSSpectrum() sframe.setMSLevel(mslevel) sframe.setRT(time) sframe.setFloatDataArrays([fda]) p = pyopenms.Precursor() if msms == 2: p.setMZ(center) p.setIsolationWindowUpperOffset(width / 2.0) p.setIsolationWindowLowerOffset(width / 2.0) sframe.setPrecursors([p]) sframe.set_peaks( (mz, intens) ) sframe.sortByPosition() exp.consumeSpectrum(sframe)