Example #1
0
        public bool ValidateProductResMz(MessageBoxHelper helper, out double?productResMz)
        {
            FullScanAcquisitionMethod acquisitionMethod = AcquisitionMethod;

            productResMz = null;

            if (acquisitionMethod != FullScanAcquisitionMethod.None)
            {
                if (IsResMzAnalyzer(ProductMassAnalyzer))
                {
                    double prodResMz;
                    bool   valid = helper.ValidateDecimalTextBox(textProductAt,
                                                                 TransitionFullScan.MIN_RES_MZ,
                                                                 TransitionFullScan.MAX_RES_MZ, out prodResMz);



                    if (!valid)
                    {
                        return(false);
                    }

                    productResMz = prodResMz;
                }
            }

            return(true);
        }
Example #2
0
        public bool ValidateProductRes(MessageBoxHelper helper, out double?productRes, TabControl tabControl = null, int tabIndex = -1)
        {
            FullScanAcquisitionMethod acquisitionMethod = AcquisitionMethod;

            productRes = null;

            if (acquisitionMethod != FullScanAcquisitionMethod.None)
            {
                double minFilt, maxFilt;

                GetFilterMinMax(ProductMassAnalyzer, out minFilt, out maxFilt);

                double prodRes;
                bool   valid;
                if (null != tabControl)
                {
                    valid = helper.ValidateDecimalTextBox(tabControl, (int)TransitionSettingsUI.TABS.FullScan,
                                                          textProductRes, minFilt, maxFilt, out prodRes);
                }
                else
                {
                    valid = helper.ValidateDecimalTextBox(textProductRes, minFilt, maxFilt, out prodRes);
                }

                if (!valid)
                {
                    return(false);
                }

                productRes = prodRes;
            }

            return(true);
        }
Example #3
0
        public bool ValidateProductRes(MessageBoxHelper helper, out double?productRes)
        {
            FullScanAcquisitionMethod acquisitionMethod = AcquisitionMethod;

            productRes = null;

            if (acquisitionMethod != FullScanAcquisitionMethod.None)
            {
                double minFilt, maxFilt;

                GetFilterMinMax(ProductMassAnalyzer, out minFilt, out maxFilt);

                double prodRes;
                bool   valid = helper.ValidateDecimalTextBox(textProductRes, minFilt, maxFilt, out prodRes);

                if (!valid)
                {
                    return(false);
                }

                productRes = prodRes;
            }

            return(true);
        }
Example #4
0
        private void ExportIsolationList(
            string csvFilename, string instrumentType, FullScanAcquisitionMethod acquisitionMethod,
            ExportMethodType methodType, params string[] checkStrings)
        {
            // Set acquisition method, mass analyzer type, resolution, etc.
            if (Equals(instrumentType, ExportInstrumentType.AGILENT_TOF))
            {
                RunUI(() => SkylineWindow.ModifyDocument("Set TOF full-scan settings", doc => doc.ChangeSettings(doc.Settings.ChangeTransitionFullScan(fs => fs
                                                                                                                                                       .ChangePrecursorResolution(FullScanMassAnalyzerType.tof, 10000, null)
                                                                                                                                                       .ChangeProductResolution(FullScanMassAnalyzerType.tof, 10000, null)
                                                                                                                                                       .ChangeAcquisitionMethod(acquisitionMethod, null)))));
            }
            else
            {
                RunUI(() => SkylineWindow.ModifyDocument("Set Orbitrap full-scan settings", doc => doc.ChangeSettings(doc.Settings.ChangeTransitionFullScan(fs => fs
                                                                                                                                                            .ChangePrecursorResolution(FullScanMassAnalyzerType.orbitrap, 60000, 400)
                                                                                                                                                            .ChangeProductResolution(FullScanMassAnalyzerType.orbitrap, 60000, 400)
                                                                                                                                                            .ChangeAcquisitionMethod(acquisitionMethod, null)))));
            }

            // Open Export Method dialog, and set method to scheduled or standard.
            string csvPath         = TestContext.GetTestPath(csvFilename);
            var    exportMethodDlg = ShowDialog <ExportMethodDlg>(() => SkylineWindow.ShowExportMethodDialog(ExportFileType.IsolationList));

            RunUI(() =>
            {
                exportMethodDlg.InstrumentType = instrumentType;
                exportMethodDlg.MethodType     = methodType;
                exportMethodDlg.UseSlens       = WithSLens;
                Assert.IsFalse(exportMethodDlg.IsOptimizeTypeEnabled);
                Assert.IsTrue(exportMethodDlg.IsTargetTypeEnabled);
                Assert.IsFalse(exportMethodDlg.IsDwellTimeVisible);
                Assert.IsFalse(exportMethodDlg.IsMaxTransitionsEnabled);
            });

            if (methodType == ExportMethodType.Standard)
            {
                // Simply close the dialog.
                OkDialog(exportMethodDlg, () => exportMethodDlg.OkDialog(csvPath));
            }
            else
            {
                // Close the SchedulingOptionsDlg, then wait for export dialog to close.
                RunDlg <SchedulingOptionsDlg>(() => exportMethodDlg.OkDialog(csvPath), schedulingOptionsDlg => schedulingOptionsDlg.OkDialog());
                WaitForClosedForm(exportMethodDlg);
            }

            // Check for expected output.
            string csvOut = File.ReadAllText(csvPath);

            AssertEx.Contains(csvOut, checkStrings);
        }
Example #5
0
        public bool ValidateProductResMz(MessageBoxHelper helper, out double?productResMz, TabControl tabControl = null, int tabIndex = -1)
        {
            FullScanAcquisitionMethod acquisitionMethod = AcquisitionMethod;

            productResMz = null;

            if (acquisitionMethod != FullScanAcquisitionMethod.None)
            {
                if (IsResMzAnalyzer(ProductMassAnalyzer))
                {
                    double prodResMz;
                    bool   valid;
                    if (null != tabControl)
                    {
                        valid = helper.ValidateDecimalTextBox(tabControl, (int)TransitionSettingsUI.TABS.FullScan,
                                                              textProductAt,
                                                              TransitionFullScan.MIN_RES_MZ,
                                                              TransitionFullScan.MAX_RES_MZ, out prodResMz);
                    }
                    else
                    {
                        valid = helper.ValidateDecimalTextBox(textProductAt,
                                                              TransitionFullScan.MIN_RES_MZ,
                                                              TransitionFullScan.MAX_RES_MZ, out prodResMz);
                    }

                    if (!valid)
                    {
                        return(false);
                    }

                    productResMz = prodResMz;
                }
            }

            return(true);
        }
Example #6
0
        private void ExportIsolationList(
            string csvFilename, string instrumentType, FullScanAcquisitionMethod acquisitionMethod,
            ExportMethodType methodType, params string[] checkStrings)
        {
            // Set acquisition method, mass analyzer type, resolution, etc.
            if (Equals(instrumentType, ExportInstrumentType.AGILENT_TOF))
            {
                RunUI(() => SkylineWindow.ModifyDocument("Set TOF full-scan settings", doc => doc.ChangeSettings(doc.Settings.ChangeTransitionFullScan(fs => fs
                                                                                                                                                       .ChangePrecursorResolution(FullScanMassAnalyzerType.tof, 10000, null)
                                                                                                                                                       .ChangeProductResolution(FullScanMassAnalyzerType.tof, 10000, null)
                                                                                                                                                       .ChangeAcquisitionMethod(acquisitionMethod, null)))));
            }
            else
            {
                RunUI(() => SkylineWindow.ModifyDocument("Set Orbitrap full-scan settings", doc => doc.ChangeSettings(doc.Settings.ChangeTransitionFullScan(fs => fs
                                                                                                                                                            .ChangePrecursorResolution(FullScanMassAnalyzerType.orbitrap, 60000, 400)
                                                                                                                                                            .ChangeProductResolution(FullScanMassAnalyzerType.orbitrap, 60000, 400)
                                                                                                                                                            .ChangeAcquisitionMethod(acquisitionMethod, null)))));
            }

            // Open Export Method dialog, and set method to scheduled or standard.
            string csvPath              = TestFilesDirs[0].GetTestPath(csvFilename);
            var    exportMethodDlg      = ShowDialog <ExportMethodDlg>(() => SkylineWindow.ShowExportMethodDialog(ExportFileType.IsolationList));
            var    exportPolarityFilter =
                AsSmallMoleculesNegativeMode != RefinementSettings.ConvertToSmallMoleculesChargesMode.none &&
                SkylineWindow.Document.IsMixedPolarity() ?
                ExportPolarity.separate :
                ExportPolarity.all;

            RunUI(() =>
            {
                exportMethodDlg.InstrumentType = instrumentType;
                exportMethodDlg.MethodType     = methodType;
                exportMethodDlg.UseSlens       = WithSLens;
                exportMethodDlg.PolarityFilter = exportPolarityFilter;
                Assert.IsFalse(exportMethodDlg.IsOptimizeTypeEnabled);
                Assert.IsTrue(exportMethodDlg.IsTargetTypeEnabled);
                Assert.IsFalse(exportMethodDlg.IsDwellTimeVisible);
                Assert.IsFalse(exportMethodDlg.IsMaxTransitionsEnabled);
            });

            if (methodType == ExportMethodType.Standard)
            {
                // Simply close the dialog.
                OkDialog(exportMethodDlg, () => exportMethodDlg.OkDialog(csvPath));
            }
            else
            {
                // Close the SchedulingOptionsDlg, then wait for export dialog to close.
                RunDlg <SchedulingOptionsDlg>(() => exportMethodDlg.OkDialog(csvPath), schedulingOptionsDlg => schedulingOptionsDlg.OkDialog());
                WaitForClosedForm(exportMethodDlg);
            }

            // Check for expected output.
            var csvResult = csvPath;

            if (exportPolarityFilter == ExportPolarity.separate)
            {
                // We will have emitted two docs, one for pos and one for neg
                var ext = csvPath.Substring(csvPath.LastIndexOf('.'));
                csvResult = csvPath.Replace(ext, string.Format("_{0}_0001{1}", ExportPolarity.negative, ext));
                var csvPos = File.ReadAllText(csvPath.Replace(ext, string.Format("_{0}_0001{1}", ExportPolarity.positive, ext)));
                var csvNeg = File.ReadAllText(csvResult);
                Assert.IsFalse(csvNeg.Equals(csvPos));
            }
            string csvOut = File.ReadAllText(csvResult);

            AssertEx.Contains(csvOut, checkStrings);
        }
Example #7
0
        private IEnumerable <SpectrumFilterPair> FindFilterPairs(IsolationWindowFilter isoWin,
                                                                 FullScanAcquisitionMethod acquisitionMethod, bool ignoreIsolationScheme = false)
        {
            if (!isoWin.IsolationMz.HasValue)
            {
                return(new SpectrumFilterPair[0]); // empty
            }
            // Return cached value from dictionary if we've seen this target previously.
            var isoWinKey = isoWin;
            IList <SpectrumFilterPair> filterPairsCached;

            if (_filterPairDictionary.TryGetValue(isoWinKey, out filterPairsCached))
            {
                return(filterPairsCached);
            }

            var filterPairs = new List <SpectrumFilterPair>();

            if (acquisitionMethod == FullScanAcquisitionMethod.DIA)
            {
                var    isoTargMz    = isoWin.IsolationMz;
                double?isoTargWidth = isoWin.IsolationWidth;
                if (!ignoreIsolationScheme)
                {
                    CalcDiaIsolationValues(ref isoTargMz, ref isoTargWidth);
                }
                if (isoTargWidth.HasValue)
                {
                    // For multiple case, find the first possible value, and iterate until
                    // no longer matching or the end of the array is encountered
                    int iFilter = IndexOfFilter(isoTargMz, isoTargWidth.Value);
                    if (iFilter != -1)
                    {
                        while (iFilter < _filterMzValues.Length && CompareMz(isoTargMz,
                                                                             _filterMzValues[iFilter].Q1, isoTargWidth.Value) == 0)
                        {
                            filterPairs.Add(_filterMzValues[iFilter++]);
                        }
                    }
                }
            }
            else
            {
                // For single (Targeted) case, review all possible matches for the one closest to the
                // desired precursor m/z value.
                // per "Issue 263: Too strict about choosing only one precursor for every MS/MS scan in Targeted MS/MS",
                // if more than one match at this m/z value return a list

                double minMzDelta     = double.MaxValue;
                double mzDeltaEpsilon = Math.Min(_instrument.MzMatchTolerance, .0001);

                // Isolation width for single is based on the instrument m/z match tolerance
                var isoTargMz    = isoWin.IsolationMz;
                var isoWinSingle = new IsolationWindowFilter(isoTargMz, _instrument.MzMatchTolerance * 2);

                foreach (var filterPair in FindFilterPairs(isoWinSingle, FullScanAcquisitionMethod.DIA, true))
                {
                    double mzDelta = Math.Abs(isoTargMz - filterPair.Q1);
                    if (mzDelta < minMzDelta) // new best match
                    {
                        minMzDelta = mzDelta;
                        // are any existing matches no longer within epsilion of new best match?
                        for (int n = filterPairs.Count; n-- > 0;)
                        {
                            if ((Math.Abs(isoTargMz - filterPairs[n].Q1) - minMzDelta) > mzDeltaEpsilon)
                            {
                                filterPairs.RemoveAt(n);  // no longer a match by our new standard
                            }
                        }
                        filterPairs.Add(filterPair);
                    }
                    else if ((mzDelta - minMzDelta) <= mzDeltaEpsilon)
                    {
                        filterPairs.Add(filterPair);  // not the best, but close to it
                    }
                }
            }

            _filterPairDictionary[isoWinKey] = filterPairs;
            return(filterPairs);
        }
Example #8
0
        public SpectrumFilter(SrmDocument document, MsDataFileUri msDataFileUri, IFilterInstrumentInfo instrumentInfo,
                              IRetentionTimePredictor retentionTimePredictor = null, bool firstPass = false)
        {
            _fullScan          = document.Settings.TransitionSettings.FullScan;
            _instrument        = document.Settings.TransitionSettings.Instrument;
            _acquisitionMethod = _fullScan.AcquisitionMethod;
            if (instrumentInfo != null)
            {
                _isWatersFile = instrumentInfo.IsWatersFile;
            }
            IsFirstPass = firstPass;

            var comparer = PrecursorTextId.PrecursorTextIdComparerInstance;
            var dictPrecursorMzToFilter = new SortedDictionary <PrecursorTextId, SpectrumFilterPair>(comparer);

            if (EnabledMs || EnabledMsMs)
            {
                if (EnabledMs)
                {
                    _isHighAccMsFilter = !Equals(_fullScan.PrecursorMassAnalyzer,
                                                 FullScanMassAnalyzerType.qit);

                    if (!firstPass)
                    {
                        var key = new PrecursorTextId(SignedMz.ZERO, null, ChromExtractor.summed);  // TIC
                        dictPrecursorMzToFilter.Add(key, new SpectrumFilterPair(key, PeptideDocNode.UNKNOWN_COLOR, dictPrecursorMzToFilter.Count,
                                                                                _instrument.MinTime, _instrument.MaxTime, null, null, 0, _isHighAccMsFilter, _isHighAccProductFilter));
                        key = new PrecursorTextId(SignedMz.ZERO, null, ChromExtractor.base_peak);   // BPC
                        dictPrecursorMzToFilter.Add(key, new SpectrumFilterPair(key, PeptideDocNode.UNKNOWN_COLOR, dictPrecursorMzToFilter.Count,
                                                                                _instrument.MinTime, _instrument.MaxTime, null, null, 0, _isHighAccMsFilter, _isHighAccProductFilter));
                    }
                }
                if (EnabledMsMs)
                {
                    _isHighAccProductFilter = !Equals(_fullScan.ProductMassAnalyzer,
                                                      FullScanMassAnalyzerType.qit);

                    if (_fullScan.AcquisitionMethod == FullScanAcquisitionMethod.DIA &&
                        _fullScan.IsolationScheme.IsAllIons)
                    {
                        if (instrumentInfo != null)
                        {
                            _isWatersMse  = _isWatersFile;
                            _isAgilentMse = instrumentInfo.IsAgilentFile;
                        }
                        _mseLevel = 1;
                    }
                }

                Func <double, double> calcWindowsQ1 = _fullScan.GetPrecursorFilterWindow;
                Func <double, double> calcWindowsQ3 = _fullScan.GetProductFilterWindow;
                _minTime = _instrument.MinTime;
                _maxTime = _instrument.MaxTime;
                bool canSchedule = CanSchedule(document, retentionTimePredictor);
                // TODO: Figure out a way to turn off time sharing on first SIM scan so that
                //       times can be shared for MS1 without SIM scans
                _isSharedTime = !canSchedule;

                // If we're using bare measured drift times from spectral libraries, go get those now
                var libraryIonMobilityInfo = document.Settings.PeptideSettings.Prediction.UseLibraryDriftTimes
                    ? document.Settings.GetIonMobilities(msDataFileUri)
                    : null;

                foreach (var nodePep in document.Molecules)
                {
                    if (firstPass && !retentionTimePredictor.IsFirstPassPeptide(nodePep))
                    {
                        continue;
                    }

                    foreach (TransitionGroupDocNode nodeGroup in nodePep.Children)
                    {
                        if (nodeGroup.Children.Count == 0)
                        {
                            continue;
                        }

                        double?       minTime = _minTime, maxTime = _maxTime;
                        double?       startDriftTimeMsec = null, endDriftTimeMsec = null;
                        double        windowDT;
                        double        highEnergyDriftTimeOffsetMsec = 0;
                        DriftTimeInfo centerDriftTime               = document.Settings.PeptideSettings.Prediction.GetDriftTime(
                            nodePep, nodeGroup, libraryIonMobilityInfo, out windowDT);
                        if (centerDriftTime.DriftTimeMsec(false).HasValue)
                        {
                            startDriftTimeMsec            = centerDriftTime.DriftTimeMsec(false) - windowDT / 2; // Get the low energy drift time
                            endDriftTimeMsec              = startDriftTimeMsec + windowDT;
                            highEnergyDriftTimeOffsetMsec = centerDriftTime.HighEnergyDriftTimeOffsetMsec;
                        }

                        if (canSchedule)
                        {
                            if (RetentionTimeFilterType.scheduling_windows == _fullScan.RetentionTimeFilterType)
                            {
                                double?centerTime = null;
                                double windowRT   = 0;
                                if (retentionTimePredictor != null)
                                {
                                    centerTime = retentionTimePredictor.GetPredictedRetentionTime(nodePep);
                                }
                                else
                                {
                                    var prediction = document.Settings.PeptideSettings.Prediction;
                                    if (prediction.RetentionTime == null || !prediction.RetentionTime.IsAutoCalculated)
                                    {
                                        centerTime = document.Settings.PeptideSettings.Prediction.PredictRetentionTimeForChromImport(
                                            document, nodePep, nodeGroup, out windowRT);
                                    }
                                }
                                // Force the center time to be at least zero
                                if (centerTime.HasValue && centerTime.Value < 0)
                                {
                                    centerTime = 0;
                                }
                                if (_fullScan.RetentionTimeFilterLength != 0)
                                {
                                    windowRT = _fullScan.RetentionTimeFilterLength * 2;
                                }
                                if (centerTime != null)
                                {
                                    double startTime = centerTime.Value - windowRT / 2;
                                    double endTime   = startTime + windowRT;
                                    minTime = Math.Max(minTime ?? 0, startTime);
                                    maxTime = Math.Min(maxTime ?? double.MaxValue, endTime);
                                }
                            }
                            else if (RetentionTimeFilterType.ms2_ids == _fullScan.RetentionTimeFilterType)
                            {
                                var times = document.Settings.GetBestRetentionTimes(nodePep, msDataFileUri);
                                if (times.Length > 0)
                                {
                                    minTime = Math.Max(minTime ?? 0, times.Min() - _fullScan.RetentionTimeFilterLength);
                                    maxTime = Math.Min(maxTime ?? double.MaxValue, times.Max() + _fullScan.RetentionTimeFilterLength);
                                }
                            }
                        }

                        SpectrumFilterPair filter;
                        string             textId = nodePep.RawTextId; // Modified Sequence for peptides, or some other string for custom ions
                        var mz  = new SignedMz(nodeGroup.PrecursorMz, nodeGroup.PrecursorCharge < 0);
                        var key = new PrecursorTextId(mz, textId, ChromExtractor.summed);
                        if (!dictPrecursorMzToFilter.TryGetValue(key, out filter))
                        {
                            filter = new SpectrumFilterPair(key, nodePep.Color, dictPrecursorMzToFilter.Count, minTime, maxTime,
                                                            startDriftTimeMsec, endDriftTimeMsec, highEnergyDriftTimeOffsetMsec,
                                                            _isHighAccMsFilter, _isHighAccProductFilter);
                            dictPrecursorMzToFilter.Add(key, filter);
                        }

                        if (!EnabledMs)
                        {
                            filter.AddQ3FilterValues(from TransitionDocNode nodeTran in nodeGroup.Children
                                                     select nodeTran.Mz, calcWindowsQ3);
                        }
                        else if (!EnabledMsMs)
                        {
                            filter.AddQ1FilterValues(GetMS1MzValues(nodeGroup), calcWindowsQ1);
                        }
                        else
                        {
                            filter.AddQ1FilterValues(GetMS1MzValues(nodeGroup), calcWindowsQ1);
                            filter.AddQ3FilterValues(from TransitionDocNode nodeTran in nodeGroup.Children
                                                     where !nodeTran.IsMs1
                                                     select nodeTran.Mz, calcWindowsQ3);
                        }
                    }
                }
                _filterMzValues = dictPrecursorMzToFilter.Values.ToArray();

                var listChromKeyFilterIds = new List <ChromKey>();
                foreach (var spectrumFilterPair in _filterMzValues)
                {
                    spectrumFilterPair.AddChromKeys(listChromKeyFilterIds);
                }
                _productChromKeys = listChromKeyFilterIds.ToArray();

                // Sort a copy of the filter pairs by maximum retention time so that we can detect when
                // filters are no longer active.
                _filterRTValues = new SpectrumFilterPair[_filterMzValues.Length];
                Array.Copy(_filterMzValues, _filterRTValues, _filterMzValues.Length);
                Array.Sort(_filterRTValues, CompareByRT);
            }

            InitRTLimits();
        }
Example #9
0
        public void OkDialog()
        {
            var helper = new MessageBoxHelper(this);

            // Validate and store prediction settings
            string   massType          = comboPrecursorMass.SelectedItem.ToString();
            MassType precursorMassType = MassTypeExtension.GetEnum(massType);

            massType = comboIonMass.SelectedItem.ToString();
            MassType fragmentMassType = MassTypeExtension.GetEnum(massType);
            string   nameCE           = comboCollisionEnergy.SelectedItem.ToString();
            CollisionEnergyRegression collisionEnergy =
                Settings.Default.GetCollisionEnergyByName(nameCE);
            string nameDP = comboDeclusterPotential.SelectedItem.ToString();
            DeclusteringPotentialRegression declusteringPotential =
                Settings.Default.GetDeclusterPotentialByName(nameDP);
            string nameCoV = comboCompensationVoltage.SelectedItem.ToString();
            CompensationVoltageParameters compensationVoltage =
                Settings.Default.GetCompensationVoltageByName(nameCoV);
            string nameOptLib = comboOptimizationLibrary.SelectedItem.ToString();
            OptimizationLibrary optimizationLibrary =
                Settings.Default.GetOptimizationLibraryByName(nameOptLib);
            OptimizedMethodType optimizedMethodType = OptimizedMethodType.None;

            if (cbUseOptimized.Checked)
            {
                optimizedMethodType = OptimizedMethodTypeExtension.GetEnum(comboOptimizeType.SelectedItem.ToString());
            }
            TransitionPrediction prediction = new TransitionPrediction(precursorMassType,
                                                                       fragmentMassType, collisionEnergy,
                                                                       declusteringPotential,
                                                                       compensationVoltage,
                                                                       optimizationLibrary,
                                                                       optimizedMethodType);

            Helpers.AssignIfEquals(ref prediction, Prediction);

            // Validate and store filter settings
            int[] precursorCharges;
            int   min = TransitionGroup.MIN_PRECURSOR_CHARGE;
            int   max = TransitionGroup.MAX_PRECURSOR_CHARGE;

            if (!helper.ValidateNumberListTextBox(tabControl1, (int)TABS.Filter, textPrecursorCharges,
                                                  min, max, out precursorCharges))
            {
                return;
            }
            precursorCharges = precursorCharges.Distinct().ToArray();

            int[] productCharges;
            min = Transition.MIN_PRODUCT_CHARGE;
            max = Transition.MAX_PRODUCT_CHARGE;
            if (!helper.ValidateNumberListTextBox(tabControl1, (int)TABS.Filter, textIonCharges,
                                                  min, max, out productCharges))
            {
                return;
            }
            productCharges = productCharges.Distinct().ToArray();

            IonType[] types = TransitionFilter.ParseTypes(textIonTypes.Text, new IonType[0]);
            if (types.Length == 0)
            {
                helper.ShowTextBoxError(tabControl1, (int)TABS.Filter, textIonTypes,
                                        Resources.TransitionSettingsUI_OkDialog_Ion_types_must_contain_a_comma_separated_list_of_ion_types_a_b_c_x_y_z_and_p_for_precursor);
                return;
            }
            types = types.Distinct().ToArray();

            double exclusionWindow = 0;

            if (!string.IsNullOrEmpty(textExclusionWindow.Text) &&
                !Equals(textExclusionWindow.Text, exclusionWindow.ToString(LocalizationHelper.CurrentCulture)))
            {
                if (!helper.ValidateDecimalTextBox(tabControl1, (int)TABS.Filter, textExclusionWindow,
                                                   TransitionFilter.MIN_EXCLUSION_WINDOW, TransitionFilter.MAX_EXCLUSION_WINDOW, out exclusionWindow))
                {
                    return;
                }
            }

            string fragmentRangeFirst = TransitionFilter.GetStartFragmentNameFromLabel(comboRangeFrom.SelectedItem.ToString());
            string fragmentRangeLast  = TransitionFilter.GetEndFragmentNameFromLabel(comboRangeTo.SelectedItem.ToString());

            var  measuredIons          = _driverIons.Chosen;
            bool autoSelect            = cbAutoSelect.Checked;
            bool exclusionUseDIAWindow = FullScanSettingsControl.IsDIA() && cbExclusionUseDIAWindow.Checked;
            var  filter = new TransitionFilter(precursorCharges, productCharges, types,
                                               fragmentRangeFirst, fragmentRangeLast, measuredIons,
                                               exclusionWindow, exclusionUseDIAWindow, autoSelect);

            Helpers.AssignIfEquals(ref filter, Filter);

            // Validate and store library settings
            TransitionLibraryPick pick = TransitionLibraryPick.none;

            if (cbLibraryPick.Checked)
            {
                if (radioAll.Checked)
                {
                    pick = TransitionLibraryPick.all;
                }
                else if (radioAllAndFiltered.Checked)
                {
                    pick = TransitionLibraryPick.all_plus;
                }
                else
                {
                    pick = TransitionLibraryPick.filter;
                }
            }

            double ionMatchTolerance;

            double minTol = TransitionLibraries.MIN_MATCH_TOLERANCE;
            double maxTol = TransitionLibraries.MAX_MATCH_TOLERANCE;

            if (!helper.ValidateDecimalTextBox(tabControl1, (int)TABS.Library, textTolerance,
                                               minTol, maxTol, out ionMatchTolerance))
            {
                return;
            }

            int ionCount = Libraries.IonCount;

            if (pick != TransitionLibraryPick.none)
            {
                min = TransitionLibraries.MIN_ION_COUNT;
                max = TransitionLibraries.MAX_ION_COUNT;
                if (!helper.ValidateNumberTextBox(tabControl1, (int)TABS.Library, textIonCount,
                                                  min, max, out ionCount))
                {
                    return;
                }
            }

            TransitionLibraries libraries = new TransitionLibraries(ionMatchTolerance, ionCount, pick);

            Helpers.AssignIfEquals(ref libraries, Libraries);

            // This dialog does not yet change integration settings
            TransitionIntegration integration = _transitionSettings.Integration;

            // Validate and store instrument settings
            int minMz;

            min = TransitionInstrument.MIN_MEASUREABLE_MZ;
            max = TransitionInstrument.MAX_MEASURABLE_MZ - TransitionInstrument.MIN_MZ_RANGE;
            if (!helper.ValidateNumberTextBox(tabControl1, (int)TABS.Instrument, textMinMz, min, max, out minMz))
            {
                return;
            }
            int maxMz;

            min = minMz + TransitionInstrument.MIN_MZ_RANGE;
            max = TransitionInstrument.MAX_MEASURABLE_MZ;
            if (!helper.ValidateNumberTextBox(tabControl1, (int)TABS.Instrument, textMaxMz, min, max, out maxMz))
            {
                return;
            }
            bool   isDynamicMin = cbDynamicMinimum.Checked;
            double mzMatchTolerance;

            minTol = TransitionInstrument.MIN_MZ_MATCH_TOLERANCE;
            maxTol = TransitionInstrument.MAX_MZ_MATCH_TOLERANCE;
            if (!helper.ValidateDecimalTextBox(tabControl1, (int)TABS.Instrument, textMzMatchTolerance,
                                               minTol, maxTol, out mzMatchTolerance))
            {
                return;
            }
            int?maxTrans = null;

            if (!string.IsNullOrEmpty(textMaxTrans.Text))
            {
                int maxTransTemp;
                min = TransitionInstrument.MIN_TRANSITION_MAX;
                max = TransitionInstrument.MAX_TRANSITION_MAX;
                if (!helper.ValidateNumberTextBox(tabControl1, (int)TABS.Instrument, textMaxTrans,
                                                  min, max, out maxTransTemp))
                {
                    return;
                }
                maxTrans = maxTransTemp;
            }
            int?maxInclusions = null;

            if (!string.IsNullOrEmpty(textMaxInclusions.Text))
            {
                int maxInclusionsTemp;
                min = TransitionInstrument.MIN_INCLUSION_MAX;
                max = TransitionInstrument.MAX_INCLUSION_MAX;
                if (!helper.ValidateNumberTextBox(tabControl1, (int)TABS.Instrument, textMaxInclusions,
                                                  min, max, out maxInclusionsTemp))
                {
                    return;
                }
                maxInclusions = maxInclusionsTemp;
            }
            int?minTime = null, maxTime = null;

            min = TransitionInstrument.MIN_TIME;
            max = TransitionInstrument.MAX_TIME;
            if (!string.IsNullOrEmpty(textMinTime.Text))
            {
                int minTimeTemp;
                if (!helper.ValidateNumberTextBox(tabControl1, (int)TABS.Instrument, textMinTime,
                                                  min, max, out minTimeTemp))
                {
                    return;
                }
                minTime = minTimeTemp;
            }
            if (!string.IsNullOrEmpty(textMaxTime.Text))
            {
                int maxTimeTemp;
                if (!helper.ValidateNumberTextBox(tabControl1, (int)TABS.Instrument, textMaxTime,
                                                  min, max, out maxTimeTemp))
                {
                    return;
                }
                maxTime = maxTimeTemp;
            }
            if (minTime.HasValue && maxTime.HasValue && maxTime.Value - minTime.Value < TransitionInstrument.MIN_TIME_RANGE)
            {
                helper.ShowTextBoxError(tabControl1, (int)TABS.Instrument, textMaxTime,
                                        string.Format(Resources.TransitionSettingsUI_OkDialog_The_allowable_retention_time_range__0__to__1__must_be_at_least__2__minutes_apart,
                                                      minTime, maxTime, TransitionInstrument.MIN_TIME_RANGE));
                return;
            }

            TransitionInstrument instrument = new TransitionInstrument(minMz,
                                                                       maxMz, isDynamicMin, mzMatchTolerance, maxTrans, maxInclusions, minTime, maxTime);

            Helpers.AssignIfEquals(ref instrument, Instrument);

            // Validate and store full-scan settings

            // If high resolution MS1 filtering is enabled, make sure precursor m/z type
            // is monoisotopic and isotope enrichments are set
            FullScanPrecursorIsotopes precursorIsotopes = PrecursorIsotopesCurrent;
            FullScanMassAnalyzerType  precursorAnalyzerType = PrecursorMassAnalyzer;

            if (precursorIsotopes != FullScanPrecursorIsotopes.None &&
                precursorAnalyzerType != FullScanMassAnalyzerType.qit)
            {
                if (precursorMassType != MassType.Monoisotopic)
                {
                    MessageDlg.Show(this, Resources.TransitionSettingsUI_OkDialog_High_resolution_MS1_filtering_requires_use_of_monoisotopic_precursor_masses);
                    tabControl1.SelectedIndex = (int)TABS.Prediction;
                    comboPrecursorMass.Focus();
                    return;
                }

                if (FullScanSettingsControl.Enrichments == null)
                {
                    tabControl1.SelectedIndex = (int)TABS.FullScan;
                    MessageDlg.Show(GetParentForm(this), Resources.TransitionSettingsUI_OkDialog_Isotope_enrichment_settings_are_required_for_MS1_filtering_on_high_resolution_mass_spectrometers);
                    FullScanSettingsControl.ComboEnrichmentsSetFocus();
                    return;
                }
            }

            IsolationScheme           isolationScheme = FullScanSettingsControl.IsolationScheme;
            FullScanAcquisitionMethod acquisitionMethod = AcquisitionMethod;

            if (isolationScheme == null && acquisitionMethod == FullScanAcquisitionMethod.DIA)
            {
                tabControl1.SelectedIndex = (int)TABS.FullScan;
                MessageDlg.Show(this, Resources.TransitionSettingsUI_OkDialog_An_isolation_scheme_is_required_to_match_multiple_precursors);
                FullScanSettingsControl.ComboIsolationSchemeSetFocus();
                return;
            }

            if (isolationScheme != null && isolationScheme.WindowsPerScan.HasValue && !maxInclusions.HasValue)
            {
                MessageDlg.Show(this, Resources.TransitionSettingsUI_OkDialog_Before_performing_a_multiplexed_DIA_scan_the_instrument_s_firmware_inclusion_limit_must_be_specified);
                tabControl1.SelectedIndex = (int)TABS.Instrument;
                textMaxInclusions.Focus();
                return;
            }

            if (FullScanSettingsControl.IsDIA() && cbExclusionUseDIAWindow.Checked)
            {
                if (FullScanSettingsControl.IsolationScheme.IsAllIons)
                {
                    MessageDlg.Show(this, Resources.TransitionSettingsUI_OkDialog_Cannot_use_DIA_window_for_precusor_exclusion_when__All_Ions__is_selected_as_the_isolation_scheme___To_use_the_DIA_window_for_precusor_exclusion__change_the_isolation_scheme_in_the_Full_Scan_settings_);
                    tabControl1.SelectedIndex = (int)TABS.Filter;
                    cbExclusionUseDIAWindow.Focus();
                    return;
                }
                if (FullScanSettingsControl.IsolationScheme.FromResults)
                {
                    MessageDlg.Show(this, Resources.TransitionSettingsUI_OkDialog_Cannot_use_DIA_window_for_precursor_exclusion_when_isolation_scheme_does_not_contain_prespecified_windows___Please_select_an_isolation_scheme_with_prespecified_windows_);
                    tabControl1.SelectedIndex = (int)TABS.Filter;
                    cbExclusionUseDIAWindow.Focus();
                    return;
                }
            }

            TransitionFullScan fullScan;

            if (!FullScanSettingsControl.ValidateFullScanSettings(helper, out fullScan, tabControl1, (int)TABS.FullScan))
            {
                return;
            }

            Helpers.AssignIfEquals(ref fullScan, FullScan);

            TransitionSettings settings = new TransitionSettings(prediction,
                                                                 filter, libraries, integration, instrument, fullScan);

            // Only update, if anything changed
            if (!Equals(settings, _transitionSettings))
            {
                if (!_parent.ChangeSettingsMonitored(this, Resources.TransitionSettingsUI_OkDialog_Changing_transition_settings,
                                                     s => s.ChangeTransitionSettings(settings)))
                {
                    return;
                }
                _transitionSettings = settings;
            }

            DialogResult = DialogResult.OK;
        }
        private void ExportIsolationList(
            string csvFilename, string instrumentType, FullScanAcquisitionMethod acquisitionMethod,
            ExportMethodType methodType, params string[] checkStrings)
        {
            // Set acquisition method, mass analyzer type, resolution, etc.
            if (Equals(instrumentType, ExportInstrumentType.AGILENT_TOF))
            {
                RunUI(() => SkylineWindow.ModifyDocument("Set TOF full-scan settings", doc => doc.ChangeSettings(doc.Settings.ChangeTransitionFullScan(fs => fs
                    .ChangePrecursorResolution(FullScanMassAnalyzerType.tof, 10000, null)
                    .ChangeProductResolution(FullScanMassAnalyzerType.tof, 10000, null)
                    .ChangeAcquisitionMethod(acquisitionMethod, null)))));
            }
            else
            {
                RunUI(() => SkylineWindow.ModifyDocument("Set Orbitrap full-scan settings", doc => doc.ChangeSettings(doc.Settings.ChangeTransitionFullScan(fs => fs
                    .ChangePrecursorResolution(FullScanMassAnalyzerType.orbitrap, 60000, 400)
                    .ChangeProductResolution(FullScanMassAnalyzerType.orbitrap, 60000, 400)
                    .ChangeAcquisitionMethod(acquisitionMethod, null)))));
            }

            // Open Export Method dialog, and set method to scheduled or standard.
            string csvPath = TestContext.GetTestPath(csvFilename);
            var exportMethodDlg = ShowDialog<ExportMethodDlg>(() => SkylineWindow.ShowExportMethodDialog(ExportFileType.IsolationList));
            RunUI(() =>
            {
                exportMethodDlg.InstrumentType = instrumentType;
                exportMethodDlg.MethodType = methodType;
                exportMethodDlg.UseSlens = WithSLens;
                Assert.IsFalse(exportMethodDlg.IsOptimizeTypeEnabled);
                Assert.IsTrue(exportMethodDlg.IsTargetTypeEnabled);
                Assert.IsFalse(exportMethodDlg.IsDwellTimeVisible);
                Assert.IsFalse(exportMethodDlg.IsMaxTransitionsEnabled);
            });

            if (methodType == ExportMethodType.Standard)
            {
                // Simply close the dialog.
                OkDialog(exportMethodDlg, ()=> exportMethodDlg.OkDialog(csvPath));
            }
            else
            {
                // Close the SchedulingOptionsDlg, then wait for export dialog to close.
                RunDlg<SchedulingOptionsDlg>(() => exportMethodDlg.OkDialog(csvPath), schedulingOptionsDlg => schedulingOptionsDlg.OkDialog());
                WaitForClosedForm(exportMethodDlg);
            }

            // Check for expected output.
            string csvOut = File.ReadAllText(csvPath);
            AssertEx.Contains(csvOut, checkStrings);
        }
Example #11
0
        public SpectrumFilter(SrmDocument document, MsDataFileUri msDataFileUri, IFilterInstrumentInfo instrumentInfo,
            IRetentionTimePredictor retentionTimePredictor = null, bool firstPass = false)
        {
            _fullScan = document.Settings.TransitionSettings.FullScan;
            _instrument = document.Settings.TransitionSettings.Instrument;
            _acquisitionMethod = _fullScan.AcquisitionMethod;
            if (instrumentInfo != null)
                _isWatersFile = instrumentInfo.IsWatersFile;
            IsFirstPass = firstPass;

            var comparer = PrecursorTextId.PrecursorTextIdComparerInstance;
            var dictPrecursorMzToFilter = new SortedDictionary<PrecursorTextId, SpectrumFilterPair>(comparer);

            if (EnabledMs || EnabledMsMs)
            {
                if (EnabledMs)
                {
                    _isHighAccMsFilter = !Equals(_fullScan.PrecursorMassAnalyzer,
                        FullScanMassAnalyzerType.qit);

                    if (!firstPass)
                    {
                        var key = new PrecursorTextId(0, null, ChromExtractor.summed);  // TIC
                        dictPrecursorMzToFilter.Add(key, new SpectrumFilterPair(key, PeptideDocNode.UNKNOWN_COLOR, dictPrecursorMzToFilter.Count,
                            _instrument.MinTime, _instrument.MaxTime, null, null, 0, _isHighAccMsFilter, _isHighAccProductFilter));
                        key = new PrecursorTextId(0, null, ChromExtractor.base_peak);   // BPC
                        dictPrecursorMzToFilter.Add(key, new SpectrumFilterPair(key, PeptideDocNode.UNKNOWN_COLOR, dictPrecursorMzToFilter.Count,
                            _instrument.MinTime, _instrument.MaxTime, null, null, 0, _isHighAccMsFilter, _isHighAccProductFilter));
                    }
                }
                if (EnabledMsMs)
                {
                    _isHighAccProductFilter = !Equals(_fullScan.ProductMassAnalyzer,
                        FullScanMassAnalyzerType.qit);

                    if (_fullScan.AcquisitionMethod == FullScanAcquisitionMethod.DIA &&
                        _fullScan.IsolationScheme.IsAllIons)
                    {
                        if (instrumentInfo != null)
                        {
                            _isWatersMse = _isWatersFile;
                            _isAgilentMse = instrumentInfo.IsAgilentFile;
                        }
                        _mseLevel = 1;
                    }
                }

                Func<double, double> calcWindowsQ1 = _fullScan.GetPrecursorFilterWindow;
                Func<double, double> calcWindowsQ3 = _fullScan.GetProductFilterWindow;
                _minTime = _instrument.MinTime;
                _maxTime = _instrument.MaxTime;
                bool canSchedule = CanSchedule(document, retentionTimePredictor);
                // TODO: Figure out a way to turn off time sharing on first SIM scan so that
                //       times can be shared for MS1 without SIM scans
                _isSharedTime = !canSchedule;

                // If we're using bare measured drift times from spectral libraries, go get those now
                var libraryIonMobilityInfo = document.Settings.PeptideSettings.Prediction.UseLibraryDriftTimes
                    ? document.Settings.GetIonMobilities(msDataFileUri)
                    : null;

                foreach (var nodePep in document.Molecules)
                {
                    if (firstPass && !retentionTimePredictor.IsFirstPassPeptide(nodePep))
                        continue;

                    foreach (TransitionGroupDocNode nodeGroup in nodePep.Children)
                    {
                        if (nodeGroup.Children.Count == 0)
                            continue;

                        double? minTime = _minTime, maxTime = _maxTime;
                        double? startDriftTimeMsec = null, endDriftTimeMsec = null;
                        double windowDT;
                        double highEnergyDriftTimeOffsetMsec = 0;
                        DriftTimeInfo centerDriftTime = document.Settings.PeptideSettings.Prediction.GetDriftTime(
                            nodePep, nodeGroup, libraryIonMobilityInfo, out windowDT);
                        if (centerDriftTime.DriftTimeMsec(false).HasValue)
                        {
                            startDriftTimeMsec = centerDriftTime.DriftTimeMsec(false) - windowDT / 2; // Get the low energy drift time
                            endDriftTimeMsec = startDriftTimeMsec + windowDT;
                            highEnergyDriftTimeOffsetMsec = centerDriftTime.HighEnergyDriftTimeOffsetMsec;
                        }

                        if (canSchedule)
                        {
                            if (RetentionTimeFilterType.scheduling_windows == _fullScan.RetentionTimeFilterType)
                            {
                                double? centerTime = null;
                                double windowRT = 0;
                                if (retentionTimePredictor != null)
                                {
                                    centerTime = retentionTimePredictor.GetPredictedRetentionTime(nodePep);
                                }
                                else
                                {
                                    var prediction = document.Settings.PeptideSettings.Prediction;
                                    if (prediction.RetentionTime == null || !prediction.RetentionTime.IsAutoCalculated)
                                    {
                                        centerTime = document.Settings.PeptideSettings.Prediction.PredictRetentionTimeForChromImport(
                                            document, nodePep, nodeGroup, out windowRT);
                                    }
                                }
                                // Force the center time to be at least zero
                                if (centerTime.HasValue && centerTime.Value < 0)
                                    centerTime = 0;
                                if (_fullScan.RetentionTimeFilterLength != 0)
                                {
                                    windowRT = _fullScan.RetentionTimeFilterLength * 2;
                                }
                                if (centerTime != null)
                                {
                                    double startTime = centerTime.Value - windowRT / 2;
                                    double endTime = startTime + windowRT;
                                    minTime = Math.Max(minTime ?? 0, startTime);
                                    maxTime = Math.Min(maxTime ?? double.MaxValue, endTime);
                                }
                            }
                            else if (RetentionTimeFilterType.ms2_ids == _fullScan.RetentionTimeFilterType)
                            {
                                var times = document.Settings.GetBestRetentionTimes(nodePep, msDataFileUri);
                                if (times.Length > 0)
                                {
                                    minTime = Math.Max(minTime ?? 0, times.Min() - _fullScan.RetentionTimeFilterLength);
                                    maxTime = Math.Min(maxTime ?? double.MaxValue, times.Max() + _fullScan.RetentionTimeFilterLength);
                                }
                            }
                        }

                        SpectrumFilterPair filter;
                        string textId = nodePep.RawTextId; // Modified Sequence for peptides, or some other string for custom ions
                        double mz = nodeGroup.PrecursorMz;
                        var key = new PrecursorTextId(mz, textId, ChromExtractor.summed);
                        if (!dictPrecursorMzToFilter.TryGetValue(key, out filter))
                        {
                            filter = new SpectrumFilterPair(key, nodePep.Color, dictPrecursorMzToFilter.Count, minTime, maxTime,
                                startDriftTimeMsec, endDriftTimeMsec, highEnergyDriftTimeOffsetMsec,
                                _isHighAccMsFilter, _isHighAccProductFilter);
                            dictPrecursorMzToFilter.Add(key, filter);
                        }

                        if (!EnabledMs)
                        {
                            filter.AddQ3FilterValues(from TransitionDocNode nodeTran in nodeGroup.Children
                                                     select nodeTran.Mz, calcWindowsQ3);
                        }
                        else if (!EnabledMsMs)
                        {
                            filter.AddQ1FilterValues(GetMS1MzValues(nodeGroup), calcWindowsQ1);
                        }
                        else
                        {
                            filter.AddQ1FilterValues(GetMS1MzValues(nodeGroup), calcWindowsQ1);
                            filter.AddQ3FilterValues(from TransitionDocNode nodeTran in nodeGroup.Children
                                                     where !nodeTran.IsMs1
                                                     select nodeTran.Mz, calcWindowsQ3);
                        }
                    }
                }
                _filterMzValues = dictPrecursorMzToFilter.Values.ToArray();

                var listChromKeyFilterIds = new List<ChromKey>();
                foreach (var spectrumFilterPair in _filterMzValues)
                {
                    spectrumFilterPair.AddChromKeys(listChromKeyFilterIds);
                }
                _productChromKeys = listChromKeyFilterIds.ToArray();

                // Sort a copy of the filter pairs by maximum retention time so that we can detect when
                // filters are no longer active.
                _filterRTValues = new SpectrumFilterPair[_filterMzValues.Length];
                Array.Copy(_filterMzValues, _filterRTValues, _filterMzValues.Length);
                Array.Sort(_filterRTValues, CompareByRT);
            }

            InitRTLimits();
        }
Example #12
0
        private IEnumerable<SpectrumFilterPair> FindFilterPairs(IsolationWindowFilter isoWin,
            FullScanAcquisitionMethod acquisitionMethod, bool ignoreIsolationScheme = false)
        {
            if (!isoWin.IsolationMz.HasValue)
                return new SpectrumFilterPair[0]; // empty

            // Return cached value from dictionary if we've seen this target previously.
            var isoWinKey = isoWin;
            IList<SpectrumFilterPair> filterPairsCached;
            if (_filterPairDictionary.TryGetValue(isoWinKey, out filterPairsCached))
            {
                return filterPairsCached;
            }

            var filterPairs = new List<SpectrumFilterPair>();
            if (acquisitionMethod == FullScanAcquisitionMethod.DIA)
            {
                double isoTargMz = isoWin.IsolationMz.Value;
                double? isoTargWidth = isoWin.IsolationWidth;
                if (!ignoreIsolationScheme)
                {
                    CalcDiaIsolationValues(ref isoTargMz, ref isoTargWidth);
                }
                if (isoTargWidth.HasValue)
                {
                    // For multiple case, find the first possible value, and iterate until
                    // no longer matching or the end of the array is encountered
                    int iFilter = IndexOfFilter(isoTargMz, isoTargWidth.Value);
                    if (iFilter != -1)
                    {
                        while (iFilter < _filterMzValues.Length && CompareMz(isoTargMz,
                            _filterMzValues[iFilter].Q1, isoTargWidth.Value) == 0)
                            filterPairs.Add(_filterMzValues[iFilter++]);
                    }
                }
            }
            else
            {
                // For single (Targeted) case, review all possible matches for the one closest to the
                // desired precursor m/z value.
                // per "Issue 263: Too strict about choosing only one precursor for every MS/MS scan in Targeted MS/MS",
                // if more than one match at this m/z value return a list

                double minMzDelta = double.MaxValue;
                double mzDeltaEpsilon = Math.Min(_instrument.MzMatchTolerance, .0001);

                // Isolation width for single is based on the instrument m/z match tolerance
                double isoTargMz = isoWin.IsolationMz.Value;
                var isoWinSingle = new IsolationWindowFilter(isoTargMz, _instrument.MzMatchTolerance * 2);

                foreach (var filterPair in FindFilterPairs(isoWinSingle, FullScanAcquisitionMethod.DIA, true))
                {
                    double mzDelta = Math.Abs(isoTargMz - filterPair.Q1);
                    if (mzDelta < minMzDelta) // new best match
                    {
                        minMzDelta = mzDelta;
                        // are any existing matches no longer within epsilion of new best match?
                        for (int n = filterPairs.Count; n-- > 0; )
                        {
                            if ((Math.Abs(isoTargMz - filterPairs[n].Q1) - minMzDelta) > mzDeltaEpsilon)
                            {
                                filterPairs.RemoveAt(n);  // no longer a match by our new standard
                            }
                        }
                        filterPairs.Add(filterPair);
                    }
                    else if ((mzDelta - minMzDelta) <= mzDeltaEpsilon)
                    {
                        filterPairs.Add(filterPair);  // not the best, but close to it
                    }
                }
            }

            _filterPairDictionary[isoWinKey] = filterPairs;
            return filterPairs;
        }