def add_gaussv_noise_ic(ic: IonChromatogram, scale: int, cutoff: int, prop: float): """ Adds noise to an ic. The noise value is drawn from a normal distribution, the scale of this distribution depends on the value of the ic at the point where the noise is being added :param ic: The IonChromatogram :type ic: pyms.IonChromatogram.IonChromatogram :param cutoff: The level below which the intensity of the ic at that point has no effect on the scale of the noise distribution :type cutoff: int :param scale: The scale of the normal distribution for ic values below the cutoff is modified for values above the cutoff :type scale: int :param prop: For ic values above the cutoff, the scale is multiplied by the ic value multiplied by prop :type prop: float :author: Sean O'Callaghan """ noise = numpy.zeros(len(ic)) i_array = ic.get_intensity_array() # time_list = ic.get_time_list() for i in range(len(ic)): if i_array[i] < cutoff: noise[i] = numpy.random.normal(0.0, scale, 1) else: noise[i] = numpy.random.normal(0.0, scale * i_array[i] * prop, 1) i_array_with_noise = noise + i_array ic.set_intensity_array(i_array_with_noise)
def get_maxima_list(ic: IonChromatogram, points: List = 3) -> int: """ List of retention time and intensity of local maxima for ion :param ic: An :class:`~pyms.IonChromatogram.IonChromatogram` object :type ic: ~pyms.IonChromatogram.IonChromatogram :param points: Number of scans over which to consider a maxima to be a peak. Default ``3`` :type points: int :return: A list of retention time and intensity of local maxima for ion :rtype: list :author: Andrew Isaac, Dominic Davis-Foster (type assertions) """ if not isinstance(ic, IonChromatogram): raise TypeError("'ic' must be an IonChromatogram object") if not isinstance(points, int): raise TypeError("'points' must be an integer") peak_point = get_maxima_indices(ic.intensity_array, points) mlist = [] for index in range(len(peak_point)): rt = ic.get_time_at_index(peak_point[index]) intensity = ic.get_intensity_at_index(peak_point[index]) mlist.append([rt, intensity]) return mlist
def test_IonChromatogram(im, tic): # get the first ion chromatogram of the IntensityMatrix ic = im.get_ic_at_index(0) assert isinstance(ic, IonChromatogram) assert not ic.is_tic() # get the ion chromatogram for m/z = 73 ic = im.get_ic_at_mass(73) assert isinstance(ic, IonChromatogram) assert not ic.is_tic() assert isinstance(tic, IonChromatogram) assert tic.is_tic() # Errors for obj in [test_string, *test_numbers, *test_sequences, test_dict]: with pytest.raises(TypeError): IonChromatogram(obj, tic.time_list) for obj in [test_string, *test_numbers, test_list_strs, test_dict]: with pytest.raises(TypeError): IonChromatogram(tic.intensity_array, obj) for obj in [test_string, *test_sequences, test_dict]: with pytest.raises(TypeError): IonChromatogram(tic.intensity_array, tic.time_list, mass=obj) with pytest.raises(ValueError): IonChromatogram(tic.intensity_array, test_list_ints)
def plot_tic(self, tic: IonChromatogram, minutes: bool = False, **kwargs): """ Plots a Total Ion Chromatogram. :param tic: Total Ion Chromatogram. :param minutes: Whether to show the time in minutes. :Other Parameters: :class:`matplotlib.lines.Line2D` properties. Used to specify properties like a line label (for auto legends), linewidth, antialiasing, marker face color. Example:: >>> plot_tic(data.tic, label='TIC', linewidth=2) See https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.lines.Line2D.html for the list of possible kwargs """ if not isinstance(tic, IonChromatogram) or not tic.is_tic(): raise TypeError("'tic' must be an Ion Chromatogram object representing a total ion chromatogram") plot = plot_ic(self.ax, tic, minutes, **kwargs) self.__tic_ic_plots.append(plot) return plot
def add_gaussc_noise_ic(ic: IonChromatogram, scale: float): """ Adds noise drawn from a normal distribution with constant scale to an ion chromatogram :param ic: The ion Chromatogram :type ic: pyms.IonChromatogram.IonChromatogram :param scale: The scale of the normal distribution :type scale: float :author: Sean O'Callaghan """ noise = numpy.random.normal(0.0, scale, (len(ic))) i_array_with_noise = ic.get_intensity_array() + noise ic.set_intensity_array(i_array_with_noise)
def get_ic_at_index(self, ix): """ Returns the ion chromatogram at the specified index :param ix: Index of an ion chromatogram in the intensity data matrix :type ix: int :return: Ion chromatogram at given index :rtype: pyms.IonChromatogram.IonChromatogram :authors: Qiao Wang, Andrew Isaac, Vladimir Likic """ if not isinstance(ix, int): raise TypeError("'ix' must be an integer") ia = [] for i in range(len(self._intensity_array)): ia.append(self._intensity_array[i][ix]) ic_ia = numpy.array(ia) mass = self.get_mass_at_index(ix) rt = copy.deepcopy(self._time_list) return IonChromatogram(ic_ia, rt, mass)
def get_maxima_list_reduced(ic: IonChromatogram, mp_rt: float, points: int = 13, window: int = 3) -> List: """ List of retention time and intensity of local maxima for ion. Only peaks around a specific retention time are recorded Created for use with gap filling algorithm. :param ic: An :class:`~pyms.IonChromatogram.IonChromatogram` object :type ic: ~pyms.IonChromatogram.IonChromatogram :param mp_rt: The retention time of the missing peak :type mp_rt: float :param points: Number of scans over which to consider a maxima to be a peak. Default ``13`` :type points: int, optional :param window: The window around the ``mp_rt`` where peaks should be recorded. Default ``3`` :type window: int, optional :return: A list of retention time and intensity of local maxima for ion :rtype: list :author: Andrew Isaac, Dominic Davis-Foster (type assertions) """ if not isinstance(ic, IonChromatogram): raise TypeError("'ic' must be an IonChromatogram object") if not isinstance(mp_rt, Number): raise TypeError("'mp_rt' must be an integer") # if not isinstance(scans, int): # raise TypeError("'scans' must be an integer") peak_point = get_maxima_indices(ic.intensity_array, points) maxima_list = [] for index in range(len(peak_point)): rt = ic.get_time_at_index(peak_point[index]) if (rt > float(mp_rt) - window) and (rt < float(mp_rt) + window): intensity = ic.get_intensity_at_index(peak_point[index]) maxima_list.append([rt, intensity]) else: pass return maxima_list
def test_equality(tic, im): assert tic == IonChromatogram(tic.intensity_array, tic.time_list) assert tic != im.get_ic_at_index(0) assert tic != test_string assert tic != test_int assert tic != test_float assert tic != test_list_ints assert tic != test_list_strs assert tic != test_dict assert tic != test_tuple
def window_sele_points(ic: IonChromatogram, window_sele: Union[int, str], half_window: bool = False) -> int: """ Converts window selection parameter into points based on the time step in an ion chromatogram :param ic: ion chromatogram object relevant for the conversion :type ic: pyms.IonChromatogram.IonChromatogram :param window_sele: The window selection parameter. This can be an integer or time string. If integer, taken as the number of points. If a string, must of the form "<NUMBER>s" or "<NUMBER>m", specifying a time in seconds or minutes, respectively :type window_sele: int or str :param half_window: Specifies whether to return half-window :type half_window: bool :return: The number of points in the window :rtype: int :author: Vladimir Likic """ if not isinstance(window_sele, int) and not isinstance(window_sele, str): raise TypeError("'window' must be an integer or a string") if isinstance(window_sele, int): if half_window: if window_sele % 2 == 0: raise TypeError("window must be an odd number of points") else: points = int(math.floor(window_sele * 0.5)) else: points = window_sele else: time = time_str_secs(window_sele) time_step = ic.get_time_step() if half_window: time = time * 0.5 points = int(math.floor(time / time_step)) if half_window: if points < 1: raise ValueError(f"window too small (half window={points:d})") else: if points < 2: raise ValueError(f"window too small (window={points:d})") return points
def tic(self) -> IonChromatogram: """ Returns the TIC of the intensity matrix. .. versionadded:: 2.3.0 """ intensity_list = [] for i in range(len(self._intensity_array)): intensity_list.append(sum(self._intensity_array[i])) return IonChromatogram(numpy.array(intensity_list), self._time_list[:], None)
def get_maxima_list_reduced( ic: IonChromatogram, mp_rt: float, points: int = 13, window: int = 3, ) -> List[Tuple[float, float]]: """ List of retention time and intensity of local maxima for ion. | Only peaks around a specific retention time are recorded. | Created for use with gap filling algorithm. :param ic: :param mp_rt: The retention time of the missing peak :param points: Number of scans over which to consider a maxima to be a peak. :param window: The window around ``mp_rt`` where peaks should be recorded. :return: A list of 2-element tuple containing the retention time and intensity of local maxima for each ion. :author: Andrew Isaac, Dominic Davis-Foster (type assertions) """ if not isinstance(ic, IonChromatogram): raise TypeError("'ic' must be an IonChromatogram object") if not is_number(mp_rt): raise TypeError("'mp_rt' must be a number") peak_point = get_maxima_indices(ic.intensity_array, points) maxima_list = [] for index in range(len(peak_point)): rt = ic.get_time_at_index(peak_point[index]) if (rt > float(mp_rt) - window) and (rt < float(mp_rt) + window): intensity = ic.get_intensity_at_index(peak_point[index]) maxima_list.append((rt, intensity)) return maxima_list
def test_intensity_array(tic, im): tic = copy.deepcopy(tic) assert isinstance(tic.intensity_array, numpy.ndarray) assert all(numpy.equal(IonChromatogram(tic.intensity_array, tic.time_list).intensity_array, tic.intensity_array)) ic = im.get_ic_at_index(0) tic.intensity_array = ic.intensity_array assert all(numpy.equal(tic.intensity_array, ic.intensity_array)) assert isinstance(tic.intensity_array, numpy.ndarray) assert isinstance(tic.intensity_array[0], float) assert tic.intensity_array[0] == 0.0 assert tic.intensity_array[2] == 622.0
def _calc_tic(self) -> None: """ Calculate the total ion chromatogram. :authors: Qiao Wang, Andrew Isaac, Vladimir Likic """ intensities = [] for scan in self._scan_list: intensities.append(sum(scan.intensity_list)) ia = numpy.array(intensities) rt = copy.deepcopy(self._time_list) tic = IonChromatogram(ia, rt) self._tic = tic
def test_success(self, im, tic): # get the first ion chromatogram of the IntensityMatrix ic = im.get_ic_at_index(0) assert isinstance(ic, IonChromatogram) assert not ic.is_tic() # get the ion chromatogram for m/z = 73 ic = im.get_ic_at_mass(73) assert isinstance(ic, IonChromatogram) assert not ic.is_tic() assert isinstance(tic, IonChromatogram) assert tic.is_tic() with pytest.raises( ValueError, match="'intensity_list' and 'time_list' differ in length"): IonChromatogram(tic.intensity_array, test_list_ints)
def sum_maxima(im: IntensityMatrix, points: int = 3, scans: int = 1) -> IonChromatogram: """ Reconstruct the TIC as sum of maxima :param im: An :class:`~pyms.IntensityMatrix.IntensityMatrix` object :type im: ~pyms.IntensityMatrix.IntensityMatrix :param points: Peak if maxima over 'points' number of scans. Default ``3`` :type points: int, optional :param scans: Number of scans to combine peaks from to compensate for spectra skewing. Default ``1`` :type scans: int, optional :return: The reconstructed TIC :rtype: ~pyms.IonChromatogram.IonChromatogram :author: Andrew Isaac, Dominic Davis-Foster (type assertions) """ if not isinstance(im, IntensityMatrix): raise TypeError("'im' must be an IntensityMatrix object") if not isinstance(points, int): raise TypeError("'points' must be an integer") if not isinstance(scans, int): raise TypeError("'scans' must be an integer") maxima_im = get_maxima_matrix(im, points) sums = [] numrows = len(maxima_im) half = int(scans / 2) for row in range(numrows): val = 0 for ii in range(scans): if 0 <= row - half + ii < numrows: val += maxima_im[row - half + ii].sum() sums.append(val) tic = IonChromatogram(numpy.array(sums), im.time_list) return tic
def __calc_tic(self): """ Calculate the total ion chromatogram :return: Total ion chromatogram :rtype: pyms.IonChromatogram.IonChromatogram :author: Qiao Wang :author: Andrew Isaac :author: Vladimir Likic """ intensities = [] for scan in self._scan_list: intensities.append(sum(scan.intensity_list)) ia = numpy.array(intensities) rt = copy.deepcopy(self._time_list) tic = IonChromatogram(ia, rt) self._tic = tic
def get_ic_at_index(self, ix: int) -> IonChromatogram: """ Returns the ion chromatogram at the specified index. :param ix: Index of an ion chromatogram in the intensity data matrix. :return: Ion chromatogram at given index. :authors: Qiao Wang, Andrew Isaac, Vladimir Likic """ if not isinstance(ix, int): raise TypeError("'ix' must be an integer") ia = [intensities[ix] for intensities in self._intensity_array] ic_ia = numpy.array(ia) mass = self.get_mass_at_index(ix) rt = self._time_list[:] return IonChromatogram(ic_ia, rt, mass)
def test_errors_intensity_list(self, value, tic): with pytest.raises(TypeError): IonChromatogram(value, tic.time_list)
def test_errors_mass(self, value, tic): with pytest.raises(TypeError): IonChromatogram(tic.intensity_array, tic.time_list, mass=value)