Exemplo n.º 1
0
    def __init__(self,
                 mass_spec,
                 N,
                 scan_param_changepoints,
                 isolation_window,
                 mz_tol,
                 rt_tol,
                 min_ms1_intensity,
                 n_purity_scans=None,
                 purity_shift=None,
                 purity_threshold=0):
        super().__init__(mass_spec)
        self.last_ms1_scan = None
        self.N = np.array(N)
        if scan_param_changepoints is not None:
            self.scan_param_changepoints = np.array([0] +
                                                    scan_param_changepoints)
        else:
            self.scan_param_changepoints = np.array([0])
        self.isolation_window = np.array(
            isolation_window
        )  # the isolation window (in Dalton) to select a precursor ion
        self.mz_tol = np.array(
            mz_tol
        )  # the m/z window (ppm) to prevent the same precursor ion to be fragmented again
        self.rt_tol = np.array(
            rt_tol
        )  # the rt window to prevent the same precursor ion to be fragmented again
        self.min_ms1_intensity = min_ms1_intensity  # minimum ms1 intensity to fragment

        self.n_purity_scans = n_purity_scans
        self.purity_shift = purity_shift
        self.purity_threshold = purity_threshold

        # make sure the input are all correct
        assert len(self.N) == len(self.scan_param_changepoints) == len(
            self.isolation_window) == len(self.mz_tol) == len(self.rt_tol)
        if self.purity_threshold != 0:
            assert all(self.n_purity_scans < np.array(self.N))

        mass_spec.reset()
        current_N, current_rt_tol, idx = self._get_current_N_DEW()
        mass_spec.current_N = current_N
        mass_spec.current_DEW = current_rt_tol

        default_scan = ScanParameters()
        default_scan.set(ScanParameters.MS_LEVEL, 1)
        default_scan.set(ScanParameters.ISOLATION_WINDOWS,
                         [[DEFAULT_MS1_SCAN_WINDOW]])
        mass_spec.set_repeating_scan(default_scan)

        # register new event handlers under this controller
        mass_spec.register(IndependentMassSpectrometer.MS_SCAN_ARRIVED,
                           self.handle_scan)
        mass_spec.register(
            IndependentMassSpectrometer.ACQUISITION_STREAM_OPENING,
            self.handle_acquisition_open)
        mass_spec.register(
            IndependentMassSpectrometer.ACQUISITION_STREAM_CLOSING,
            self.handle_acquisition_closing)
Exemplo n.º 2
0
    def _process_scan(self, scan, queue_size):
        # if there's a previous ms1 scan to process
        new_tasks = []
        if self.last_ms1_scan is not None:

            rt = self.last_ms1_scan.rt

            # then get the last ms1 scan, select bin walls and create scan locations
            mzs = self.last_ms1_scan.mzs
            default_range = [
                DEFAULT_MS1_SCAN_WINDOW
            ]  # TODO: this should maybe come from somewhere else?
            locations = DiaWindows(mzs, default_range, self.dia_design,
                                   self.window_type, self.kaufmann_design,
                                   self.extra_bins, self.num_windows).locations
            logger.debug('Window locations {}'.format(locations))
            for i in range(
                    len(locations)
            ):  # define isolation window around the selected precursor ions
                isolation_windows = locations[i]
                dda_scan_params = ScanParameters()
                dda_scan_params.set(ScanParameters.MS_LEVEL, 2)
                dda_scan_params.set(ScanParameters.ISOLATION_WINDOWS,
                                    isolation_windows)
                new_tasks.append(dda_scan_params
                                 )  # push this dda scan to the mass spec queue

            # set this ms1 scan as has been processed
            self.last_ms1_scan = None
        return new_tasks
Exemplo n.º 3
0
    def __init__(self,
                 mass_spec,
                 dia_design,
                 window_type,
                 kaufmann_design,
                 extra_bins,
                 num_windows=None):
        super().__init__(mass_spec)
        self.last_ms1_scan = None
        self.dia_design = dia_design
        self.window_type = window_type
        self.kaufmann_design = kaufmann_design
        self.extra_bins = extra_bins
        self.num_windows = num_windows

        mass_spec.reset()
        default_scan = ScanParameters()
        default_scan.set(ScanParameters.MS_LEVEL, 1)
        default_scan.set(ScanParameters.ISOLATION_WINDOWS,
                         [[DEFAULT_MS1_SCAN_WINDOW]])
        mass_spec.set_repeating_scan(default_scan)

        mass_spec.register(IndependentMassSpectrometer.MS_SCAN_ARRIVED,
                           self.handle_scan)
        mass_spec.register(
            IndependentMassSpectrometer.ACQUISITION_STREAM_OPENING,
            self.handle_acquisition_open)
        mass_spec.register(
            IndependentMassSpectrometer.ACQUISITION_STREAM_CLOSING,
            self.handle_acquisition_closing)
Exemplo n.º 4
0
    def __init__(self, mass_spec, N, isolation_window, mz_tol, rt_tol,
                 min_ms1_intensity):
        super().__init__(mass_spec)
        self.last_ms1_scan = None
        self.N = N
        self.isolation_window = isolation_window  # the isolation window (in Dalton) to select a precursor ion
        self.mz_tol = mz_tol  # the m/z window (ppm) to prevent the same precursor ion to be fragmented again
        self.rt_tol = rt_tol  # the rt window to prevent the same precursor ion to be fragmented again
        self.min_ms1_intensity = min_ms1_intensity  # minimum ms1 intensity to fragment

        mass_spec.reset()
        mass_spec.current_N = N
        mass_spec.current_DEW = rt_tol

        default_scan = ScanParameters()
        default_scan.set(ScanParameters.MS_LEVEL, 1)
        default_scan.set(ScanParameters.ISOLATION_WINDOWS,
                         [[DEFAULT_MS1_SCAN_WINDOW]])
        mass_spec.set_repeating_scan(default_scan)

        # register new event handlers under this controller
        mass_spec.register(IndependentMassSpectrometer.MS_SCAN_ARRIVED,
                           self.handle_scan)
        mass_spec.register(
            IndependentMassSpectrometer.ACQUISITION_STREAM_OPENING,
            self.handle_acquisition_open)
        mass_spec.register(
            IndependentMassSpectrometer.ACQUISITION_STREAM_CLOSING,
            self.handle_acquisition_closing)
Exemplo n.º 5
0
 def __init__(self,
              mass_spec,
              controller,
              min_time,
              max_time,
              progress_bar=True,
              out_dir=None,
              out_file=None):
     """
     Initialises a synchronous environment to run the mass spec and controller
     :param mass_spec: An instance of Mass Spec object
     :param controller: An instance of Controller object
     :param min_time: start time
     :param max_time: end time
     :param progress_bar: True if a progress bar is to be shown
     """
     self.scan_channel = []
     self.task_channel = []
     self.mass_spec = mass_spec
     self.controller = controller
     self.min_time = min_time
     self.max_time = max_time
     self.progress_bar = progress_bar
     self.default_scan_params = ScanParameters()
     self.default_scan_params.set(ScanParameters.MS_LEVEL, 1)
     self.default_scan_params.set(ScanParameters.ISOLATION_WINDOWS,
                                  [[DEFAULT_MS1_SCAN_WINDOW]])
     self.default_scan_params.set(ScanParameters.ISOLATION_WIDTH,
                                  DEFAULT_ISOLATION_WIDTH)
     self.default_scan_params.set(ScanParameters.COLLISION_ENERGY,
                                  DEFAULT_COLLISION_ENERGY)
     self.default_scan_params.set(ScanParameters.POLARITY,
                                  self.mass_spec.ionisation_mode)
     self.default_scan_params.set(ScanParameters.FIRST_MASS,
                                  DEFAULT_MS1_SCAN_WINDOW[0])
     self.default_scan_params.set(ScanParameters.LAST_MASS,
                                  DEFAULT_MS1_SCAN_WINDOW[1])
     self.out_dir = out_dir
     self.out_file = out_file
Exemplo n.º 6
0
    def run(self, schedule_file, progress_bar=True):
        self.schedule = pd.read_csv(schedule_file)
        for idx, row in self.schedule.iterrows():
            target_mass = row.targetMass
            target_time = row.targetTime

            if np.isnan(target_mass):
                ms_level = 1
                isolation_windows = [[(0, 1000)]]
                precursor = None
            else:
                ms_level = 2
                mz_lower = target_mass - self.isolation_window
                mz_upper = target_mass + self.isolation_window
                isolation_windows = [[(mz_lower, mz_upper)]]
                precursor_charge = +1 if (self.mass_spec.ionisation_mode
                                          == POSITIVE) else -1
                scan_id = 0
                precursor = Precursor(precursor_mz=target_mass,
                                      precursor_intensity=0,
                                      precursor_charge=precursor_charge,
                                      precursor_scan_id=scan_id)

            dda_scan_params = ScanParameters()
            dda_scan_params.set(ScanParameters.MS_LEVEL, ms_level)
            dda_scan_params.set(ScanParameters.ISOLATION_WINDOWS,
                                isolation_windows)
            dda_scan_params.set(ScanParameters.TIME, target_time)
            if precursor:
                dda_scan_params.set(ScanParameters.PRECURSOR, precursor)
            self.mass_spec.add_task(
                dda_scan_params)  # push this scan to the mass spec queue

        if progress_bar:
            with tqdm(total=target_time, initial=0) as pbar:
                self.mass_spec.run(self.schedule, pbar=pbar)
        else:
            self.mass_spec.run(self.schedule)
Exemplo n.º 7
0
    def __init__(self,
                 mass_spec,
                 isolation_window,
                 mz_tol,
                 min_ms1_intensity,
                 min_roi_intensity,
                 min_roi_length,
                 score_method,
                 N=None,
                 rt_tol=math.inf,
                 score_params=None):
        super().__init__(mass_spec)
        self.last_ms1_scan = None
        self.N = N
        self.isolation_window = isolation_window  # the isolation window (in Dalton) to select a precursor ion
        self.mz_tol = mz_tol  # the m/z window (ppm) to prevent the same precursor ion to be fragmented again
        self.rt_tol = rt_tol  # the rt window to prevent the same precursor ion to be fragmented again
        self.min_ms1_intensity = min_ms1_intensity  # minimum ms1 intensity to fragment

        # ROI stuff
        self.min_roi_intensity = min_roi_intensity
        self.mz_units = 'Da'
        self.min_roi_length = min_roi_length

        # Score stuff
        self.score_params = score_params
        self.score_method = score_method

        # Create ROI
        self.live_roi = []
        self.dead_roi = []
        self.junk_roi = []
        self.live_roi_fragmented = []
        self.live_roi_last_rt = []  # last fragmentation time of ROI

        mass_spec.reset()
        mass_spec.current_N = N
        mass_spec.current_DEW = rt_tol
        mass_spec.use_exclusion_list = False

        default_scan = ScanParameters()
        default_scan.set(ScanParameters.MS_LEVEL, 1)
        default_scan.set(ScanParameters.ISOLATION_WINDOWS,
                         [[DEFAULT_MS1_SCAN_WINDOW]])
        mass_spec.set_repeating_scan(default_scan)

        # register new event handlers under this controller
        mass_spec.register(IndependentMassSpectrometer.MS_SCAN_ARRIVED,
                           self.handle_scan)
        mass_spec.register(
            IndependentMassSpectrometer.ACQUISITION_STREAM_OPENING,
            self.handle_acquisition_open)
        mass_spec.register(
            IndependentMassSpectrometer.ACQUISITION_STREAM_CLOSING,
            self.handle_acquisition_closing)
Exemplo n.º 8
0
    def __init__(self, mass_spec):
        super().__init__(mass_spec)
        default_scan = ScanParameters()
        default_scan.set(ScanParameters.MS_LEVEL, 1)
        default_scan.set(ScanParameters.ISOLATION_WINDOWS,
                         [[DEFAULT_MS1_SCAN_WINDOW]])

        mass_spec.reset()
        mass_spec.current_N = 0
        mass_spec.current_DEW = 0

        mass_spec.set_repeating_scan(default_scan)
        mass_spec.register(IndependentMassSpectrometer.MS_SCAN_ARRIVED,
                           self.handle_scan)
        mass_spec.register(
            IndependentMassSpectrometer.ACQUISITION_STREAM_OPENING,
            self.handle_acquisition_open)
        mass_spec.register(
            IndependentMassSpectrometer.ACQUISITION_STREAM_CLOSING,
            self.handle_acquisition_closing)
Exemplo n.º 9
0
class Environment(object):
    def __init__(self,
                 mass_spec,
                 controller,
                 min_time,
                 max_time,
                 progress_bar=True,
                 out_dir=None,
                 out_file=None):
        """
        Initialises a synchronous environment to run the mass spec and controller
        :param mass_spec: An instance of Mass Spec object
        :param controller: An instance of Controller object
        :param min_time: start time
        :param max_time: end time
        :param progress_bar: True if a progress bar is to be shown
        """
        self.scan_channel = []
        self.task_channel = []
        self.mass_spec = mass_spec
        self.controller = controller
        self.min_time = min_time
        self.max_time = max_time
        self.progress_bar = progress_bar
        self.default_scan_params = ScanParameters()
        self.default_scan_params.set(ScanParameters.MS_LEVEL, 1)
        self.default_scan_params.set(ScanParameters.ISOLATION_WINDOWS,
                                     [[DEFAULT_MS1_SCAN_WINDOW]])
        self.default_scan_params.set(ScanParameters.ISOLATION_WIDTH,
                                     DEFAULT_ISOLATION_WIDTH)
        self.default_scan_params.set(ScanParameters.COLLISION_ENERGY,
                                     DEFAULT_COLLISION_ENERGY)
        self.default_scan_params.set(ScanParameters.POLARITY,
                                     self.mass_spec.ionisation_mode)
        self.default_scan_params.set(ScanParameters.FIRST_MASS,
                                     DEFAULT_MS1_SCAN_WINDOW[0])
        self.default_scan_params.set(ScanParameters.LAST_MASS,
                                     DEFAULT_MS1_SCAN_WINDOW[1])
        self.out_dir = out_dir
        self.out_file = out_file

    def run(self):
        """
        Runs the mass spec and controller
        :return: None
        """
        # reset mass spec and set some initial values for each run
        self.mass_spec.reset()
        self.controller.reset()
        self._set_initial_values()

        # register event handlers from the controller
        self.mass_spec.register_event(
            IndependentMassSpectrometer.MS_SCAN_ARRIVED, self.add_scan)
        self.mass_spec.register_event(
            IndependentMassSpectrometer.ACQUISITION_STREAM_OPENING,
            self.controller.handle_acquisition_open)
        self.mass_spec.register_event(
            IndependentMassSpectrometer.ACQUISITION_STREAM_CLOSING,
            self.controller.handle_acquisition_closing)
        self.mass_spec.register_event(
            IndependentMassSpectrometer.STATE_CHANGED,
            self.controller.handle_state_changed)

        # run mass spec
        bar = tqdm(total=self.max_time -
                   self.min_time, initial=0) if self.progress_bar else None
        self.mass_spec.fire_event(
            IndependentMassSpectrometer.ACQUISITION_STREAM_OPENING)
        try:
            # perform one step of mass spec up to max_time
            while self.mass_spec.time < self.max_time:
                # controller._process_scan() is called here immediately when a scan is produced within a step
                scan = self.mass_spec.step()
                # update controller internal states AFTER a scan has been generated and handled
                self.controller.update_state_after_scan(scan)
                # increment progress bar
                self._update_progress_bar(bar, scan)
        except Exception as e:
            raise e
        finally:
            self.mass_spec.close()
            self.close_progress_bar(bar)
        self.write_mzML(self.out_dir, self.out_file)

    def _update_progress_bar(self, pbar, scan):
        """
        Updates progress bar based on elapsed time
        :param elapsed: Elapsed time to increment the progress bar
        :param pbar: progress bar object
        :param scan: the newly generated scan
        :return: None
        """
        if pbar is not None:
            N, DEW = self._get_N_DEW(self.mass_spec.time)
            if N is not None and DEW is not None:
                msg = '(%.3fs) ms_level=%d N=%d DEW=%d' % (
                    self.mass_spec.time, scan.ms_level, N, DEW)
            else:
                msg = '(%.3fs) ms_level=%d' % (self.mass_spec.time,
                                               scan.ms_level)
            if pbar.n + scan.scan_duration < pbar.total:
                pbar.update(scan.scan_duration)
            pbar.set_description(msg)

    def close_progress_bar(self, bar):
        if bar is not None:
            try:
                bar.close()
            except Exception as e:
                logger.warning('Failed to close progress bar: %s' % str(e))
                pass

    def add_scan(self, scan):
        """
        Adds a newly generated scan. In this case, immediately we process it in the controller without saving the scan.
        :param scan: A newly generated scan
        :return: None
        """
        self.scan_channel.append(scan)
        scan = self.scan_channel.pop(0)
        queue_size = len(self.mass_spec.get_processing_queue())
        tasks = self.controller.handle_scan(scan, queue_size)
        self.add_tasks(tasks)

    def add_tasks(self, scan_params):
        """
        Stores new tasks from the controller. In this case, immediately we pass the new tasks to the mass spec.
        :param scan_params: new tasks
        :return: None
        """
        self.task_channel.extend(scan_params)
        while len(self.task_channel) > 0:
            new_task = self.task_channel.pop(0)
            self.mass_spec.add_to_processing_queue(new_task)

    def write_mzML(self, out_dir, out_file):
        """
        Writes mzML to output file
        :param out_dir: output directory
        :param out_file: output filename
        :return: None
        """
        if out_file is None:  # if no filename provided, just quits
            return
        else:
            if out_dir is None:  # no out_dir, use only out_file
                mzml_filename = Path(out_file)
            else:  # both our_dir and out_file are provided
                mzml_filename = Path(out_dir, out_file)

        logger.debug('Writing mzML file to %s' % mzml_filename)
        try:
            precursor_information = self.controller.precursor_information
        except AttributeError:
            precursor_information = None
        writer = MzmlWriter('my_analysis', self.controller.scans,
                            precursor_information)
        writer.write_mzML(mzml_filename)
        logger.debug('mzML file successfully written!')

    def _set_initial_values(self):
        """
        Sets initial environment, mass spec start time, default scan parameters and other values
        :return: None
        """
        self.controller.set_environment(self)
        self.mass_spec.set_environment(self)
        self.mass_spec.time = self.min_time

        N, DEW = self._get_N_DEW(self.mass_spec.time)
        if N is not None:
            self.mass_spec.current_N = N
        if DEW is not None:
            self.mass_spec.current_DEW = DEW

    def get_default_scan_params(self):
        """
        Gets the default method scan parameters. Now it's set to do MS1 scan only.
        :return: the default scan parameters
        """
        return self.default_scan_params

    def _get_N_DEW(self, time):
        """
        Gets the current N and DEW depending on which controller type it is
        :return: The current N and DEW values, None otherwise
        """
        if isinstance(self.controller, PurityController):
            current_N, current_rt_tol, idx = self.controller._get_current_N_DEW(
                time)
            return current_N, current_rt_tol
        elif isinstance(self.controller, TopNController):
            return self.controller.N, self.controller.rt_tols
        else:
            return None, None
Exemplo n.º 10
0
    def _get_dda_scan_param(self, mz, intensity, isolation_width, mz_tol,
                            rt_tol, collision_energy):
        dda_scan_params = ScanParameters()
        dda_scan_params.set(ScanParameters.MS_LEVEL, 2)

        # create precursor object, assume it's all singly charged
        precursor_charge = +1 if (self.environment.mass_spec.ionisation_mode
                                  == POSITIVE) else -1
        precursor = Precursor(precursor_mz=mz,
                              precursor_intensity=intensity,
                              precursor_charge=precursor_charge,
                              precursor_scan_id=self.last_ms1_scan.scan_id)
        dda_scan_params.set(ScanParameters.PRECURSOR_MZ, precursor)

        # set the full-width isolation width, in Da
        dda_scan_params.set(ScanParameters.ISOLATION_WIDTH, isolation_width)

        # define dynamic exclusion parameters
        dda_scan_params.set(ScanParameters.DYNAMIC_EXCLUSION_MZ_TOL, mz_tol)
        dda_scan_params.set(ScanParameters.DYNAMIC_EXCLUSION_RT_TOL, rt_tol)

        # define other fragmentation parameters
        dda_scan_params.set(ScanParameters.COLLISION_ENERGY, collision_energy)
        dda_scan_params.set(ScanParameters.POLARITY,
                            self.environment.mass_spec.ionisation_mode)
        dda_scan_params.set(ScanParameters.FIRST_MASS,
                            DEFAULT_MSN_SCAN_WINDOW[0])
        dda_scan_params.set(ScanParameters.LAST_MASS,
                            DEFAULT_MSN_SCAN_WINDOW[1])
        return dda_scan_params
Exemplo n.º 11
0
    def _update_parameters(self, scan):

        # if there's a previous ms1 scan to process
        if self.last_ms1_scan is not None:

            self.current_roi_mzs = [roi.get_mean_mz() for roi in self.live_roi]
            self.current_roi_intensities = [
                roi.get_max_intensity() for roi in self.live_roi
            ]
            rt = self.last_ms1_scan.rt

            # loop over points in decreasing score
            scores = self.get_scores(self.score_method, self.score_params)
            idx = np.argsort(scores)[::-1]
            for i in idx:
                mz = self.current_roi_mzs[i]
                intensity = self.current_roi_intensities[i]

                # stopping criteria is done based on the scores
                if scores[i] <= 0:
                    self.logger.debug(
                        'Time %f Top-%d ions have been selected' %
                        (self.mass_spec.time, self.N))
                    break

                # updated fragmented list and times
                if self.live_roi_fragmented[i]:
                    continue
                self.live_roi_fragmented[i] = True
                self.live_roi_last_rt[
                    i] = rt  # TODO: May want to update this to use the time of the MS2 scan

                # send a new ms2 scan parameter to the mass spec
                dda_scan_params = ScanParameters()
                dda_scan_params.set(ScanParameters.MS_LEVEL, 2)

                # create precursor object, assume it's all singly charged
                precursor_charge = +1 if (self.mass_spec.ionisation_mode
                                          == POSITIVE) else -1
                precursor = Precursor(
                    precursor_mz=mz,
                    precursor_intensity=intensity,
                    precursor_charge=precursor_charge,
                    precursor_scan_id=self.last_ms1_scan.scan_id)
                mz_lower = mz - self.isolation_window  # Da
                mz_upper = mz + self.isolation_window  # Da
                isolation_windows = [[(mz_lower, mz_upper)]]
                dda_scan_params.set(ScanParameters.ISOLATION_WINDOWS,
                                    isolation_windows)
                dda_scan_params.set(ScanParameters.PRECURSOR, precursor)

                # save dynamic exclusion parameters too
                dda_scan_params.set(ScanParameters.DYNAMIC_EXCLUSION_MZ_TOL,
                                    self.mz_tol)
                dda_scan_params.set(ScanParameters.DYNAMIC_EXCLUSION_RT_TOL,
                                    self.rt_tol)

                # push this dda scan parameter to the mass spec queue
                self.mass_spec.add_task(dda_scan_params)

            for param in self.mass_spec.get_task_queue():
                precursor = param.get(ScanParameters.PRECURSOR)
                if precursor is not None:
                    self.logger.debug('- %s' % str(precursor))

                # set this ms1 scan as has been processed
            self.last_ms1_scan = None
Exemplo n.º 12
0
    def _update_parameters(self, scan):

        # if there's a previous ms1 scan to process
        if self.last_ms1_scan is not None:

            mzs = self.last_ms1_scan.mzs
            intensities = self.last_ms1_scan.intensities
            rt = self.last_ms1_scan.rt

            # set up current scan parameters
            current_N, current_rt_tol, idx = self._get_current_N_DEW()
            current_isolation_window = self.isolation_window[idx]
            current_mz_tol = self.mz_tol[idx]

            # calculate purities
            purities = []
            for mz_idx in range(len(self.last_ms1_scan.mzs)):
                nearby_mzs_idx = np.where(
                    abs(self.last_ms1_scan.mzs - self.last_ms1_scan.mzs[mz_idx]
                        ) < current_isolation_window)
                if len(nearby_mzs_idx[0]) == 1:
                    purities.append(1)
                else:
                    total_intensity = sum(
                        self.last_ms1_scan.intensities[nearby_mzs_idx])
                    purities.append(self.last_ms1_scan.intensities[mz_idx] /
                                    total_intensity)

            # loop over points in decreasing intensity
            fragmented_count = 0
            idx = np.argsort(intensities)[::-1]
            for i in idx:
                mz = mzs[i]
                intensity = intensities[i]
                purity = purities[i]

                # stopping criteria is after we've fragmented N ions or we found ion < min_intensity
                if fragmented_count >= current_N:
                    self.logger.debug(
                        'Time %f Top-%d ions have been selected' %
                        (self.mass_spec.time, current_N))
                    break

                if intensity < self.min_ms1_intensity:
                    self.logger.debug(
                        'Time %f Minimum intensity threshold %f reached at %f, %d'
                        % (self.mass_spec.time, self.min_ms1_intensity,
                           intensity, fragmented_count))
                    break

                # skip ion in the dynamic exclusion list of the mass spec
                if self.mass_spec.is_excluded(mz, rt):
                    continue

                if purity < self.purity_threshold:
                    purity_shift_amounts = [
                        self.purity_shift * (i - (self.n_purity_scans - 1) / 2)
                        for i in range(self.n_purity_scans)
                    ]
                    for purity_idx in range(self.n_purity_scans):
                        # send a new ms2 scan parameter to the mass spec
                        dda_scan_params = ScanParameters()
                        dda_scan_params.set(ScanParameters.MS_LEVEL, 2)
                        dda_scan_params.set(ScanParameters.N, current_N)

                        # create precursor object, assume it's all singly charged
                        precursor_charge = +1 if (
                            self.mass_spec.ionisation_mode == POSITIVE) else -1
                        precursor = Precursor(
                            precursor_mz=mz,
                            precursor_intensity=intensity,
                            precursor_charge=precursor_charge,
                            precursor_scan_id=self.last_ms1_scan.scan_id)
                        mz_lower = mz + purity_shift_amounts[
                            purity_idx] - current_isolation_window  # Da
                        mz_upper = mz + purity_shift_amounts[
                            purity_idx] + current_isolation_window  # Da
                        isolation_windows = [[(mz_lower, mz_upper)]]
                        dda_scan_params.set(ScanParameters.ISOLATION_WINDOWS,
                                            isolation_windows)
                        dda_scan_params.set(ScanParameters.PRECURSOR,
                                            precursor)

                        # save dynamic exclusion parameters too
                        dda_scan_params.set(
                            ScanParameters.DYNAMIC_EXCLUSION_MZ_TOL,
                            current_mz_tol)
                        dda_scan_params.set(
                            ScanParameters.DYNAMIC_EXCLUSION_RT_TOL,
                            current_rt_tol)

                        # push this dda scan parameter to the mass spec queue
                        self.mass_spec.add_task(dda_scan_params)
                        fragmented_count += 1
                        # need to work out what we want to do here
                else:
                    # send a new ms2 scan parameter to the mass spec
                    dda_scan_params = ScanParameters()
                    dda_scan_params.set(ScanParameters.MS_LEVEL, 2)
                    dda_scan_params.set(ScanParameters.N, current_N)

                    # create precursor object, assume it's all singly charged
                    precursor_charge = +1 if (self.mass_spec.ionisation_mode
                                              == POSITIVE) else -1
                    precursor = Precursor(
                        precursor_mz=mz,
                        precursor_intensity=intensity,
                        precursor_charge=precursor_charge,
                        precursor_scan_id=self.last_ms1_scan.scan_id)
                    mz_lower = mz - current_isolation_window  # Da
                    mz_upper = mz + current_isolation_window  # Da
                    isolation_windows = [[(mz_lower, mz_upper)]]
                    dda_scan_params.set(ScanParameters.ISOLATION_WINDOWS,
                                        isolation_windows)
                    dda_scan_params.set(ScanParameters.PRECURSOR, precursor)

                    # save dynamic exclusion parameters too
                    dda_scan_params.set(
                        ScanParameters.DYNAMIC_EXCLUSION_MZ_TOL,
                        current_mz_tol)
                    dda_scan_params.set(
                        ScanParameters.DYNAMIC_EXCLUSION_RT_TOL,
                        current_rt_tol)

                    # push this dda scan parameter to the mass spec queue
                    self.mass_spec.add_task(dda_scan_params)
                    fragmented_count += 1

            for param in self.mass_spec.get_task_queue():
                precursor = param.get(ScanParameters.PRECURSOR)
                if precursor is not None:
                    self.logger.debug('- %s' % str(precursor))

                # set this ms1 scan as has been processed
            self.last_ms1_scan = None
Exemplo n.º 13
0
    def _update_parameters(self, scan):

        # if there's a previous ms1 scan to process
        if self.last_ms1_scan is not None:

            mzs = self.last_ms1_scan.mzs
            intensities = self.last_ms1_scan.intensities
            rt = self.last_ms1_scan.rt

            # loop over points in decreasing intensity
            fragmented_count = 0
            idx = np.argsort(intensities)[::-1]
            for i in idx:
                mz = mzs[i]
                intensity = intensities[i]

                # stopping criteria is after we've fragmented N ions or we found ion < min_intensity
                if fragmented_count >= self.N:
                    self.logger.debug(
                        'Time %f Top-%d ions have been selected' %
                        (self.mass_spec.time, self.N))
                    break

                if intensity < self.min_ms1_intensity:
                    self.logger.debug(
                        'Time %f Minimum intensity threshold %f reached at %f, %d'
                        % (self.mass_spec.time, self.min_ms1_intensity,
                           intensity, fragmented_count))
                    break

                # skip ion in the dynamic exclusion list of the mass spec
                if self.mass_spec.is_excluded(mz, rt):
                    continue

                # send a new ms2 scan parameter to the mass spec
                dda_scan_params = ScanParameters()
                dda_scan_params.set(ScanParameters.MS_LEVEL, 2)

                # create precursor object, assume it's all singly charged
                precursor_charge = +1 if (self.mass_spec.ionisation_mode
                                          == POSITIVE) else -1
                precursor = Precursor(
                    precursor_mz=mz,
                    precursor_intensity=intensity,
                    precursor_charge=precursor_charge,
                    precursor_scan_id=self.last_ms1_scan.scan_id)
                mz_lower = mz - self.isolation_window  # Da
                mz_upper = mz + self.isolation_window  # Da
                isolation_windows = [[(mz_lower, mz_upper)]]
                dda_scan_params.set(ScanParameters.ISOLATION_WINDOWS,
                                    isolation_windows)
                dda_scan_params.set(ScanParameters.PRECURSOR, precursor)

                # save dynamic exclusion parameters too
                dda_scan_params.set(ScanParameters.DYNAMIC_EXCLUSION_MZ_TOL,
                                    self.mz_tol)
                dda_scan_params.set(ScanParameters.DYNAMIC_EXCLUSION_RT_TOL,
                                    self.rt_tol)

                # push this dda scan parameter to the mass spec queue
                self.mass_spec.add_task(dda_scan_params)
                fragmented_count += 1

            for param in self.mass_spec.get_task_queue():
                precursor = param.get(ScanParameters.PRECURSOR)
                if precursor is not None:
                    self.logger.debug('- %s' % str(precursor))

                # set this ms1 scan as has been processed
            self.last_ms1_scan = None