Exemple #1
0
        /// <summary>
        /// Store custom SIC values defined in CustomMZSearchValues
        /// </summary>
        /// <param name="scanList"></param>
        /// <param name="defaultSICTolerance"></param>
        /// <param name="sicToleranceIsPPM"></param>
        /// <param name="defaultScanOrAcqTimeTolerance"></param>
        public void AddCustomSICValues(
            clsScanList scanList,
            double defaultSICTolerance,
            bool sicToleranceIsPPM,
            float defaultScanOrAcqTimeTolerance)
        {
            var   scanOrAcqTimeSumCount        = 0;
            float scanOrAcqTimeSumForAveraging = 0;

            try
            {
                if (CustomMZSearchValues.Count == 0)
                {
                    return;
                }

                var scanNumScanConverter = new clsScanNumScanTimeConversion();
                RegisterEvents(scanNumScanConverter);

                foreach (var customMzSearchValue in CustomMZSearchValues)
                {
                    // Add a new parent ion entry to .ParentIons() for this custom MZ value
                    var currentParentIon = new clsParentIonInfo(customMzSearchValue.MZ);

                    if (customMzSearchValue.ScanOrAcqTimeCenter < float.Epsilon)
                    {
                        // Set the SurveyScanIndex to the center of the analysis
                        currentParentIon.SurveyScanIndex = scanNumScanConverter.FindNearestSurveyScanIndex(
                            scanList, 0.5F, eCustomSICScanTypeConstants.Relative);
                    }
                    else
                    {
                        currentParentIon.SurveyScanIndex = scanNumScanConverter.FindNearestSurveyScanIndex(
                            scanList, customMzSearchValue.ScanOrAcqTimeCenter, ScanToleranceType);
                    }

                    // Find the next MS2 scan that occurs after the survey scan (parent scan)
                    var surveyScanNumberAbsolute = 0;
                    if (currentParentIon.SurveyScanIndex < scanList.SurveyScans.Count)
                    {
                        surveyScanNumberAbsolute = scanList.SurveyScans[currentParentIon.SurveyScanIndex].ScanNumber + 1;
                    }

                    if (scanList.MasterScanOrderCount == 0)
                    {
                        currentParentIon.FragScanIndices.Add(0);
                    }
                    else
                    {
                        var fragScanIndexMatch = clsBinarySearch.BinarySearchFindNearest(
                            scanList.MasterScanNumList,
                            surveyScanNumberAbsolute,
                            clsBinarySearch.eMissingDataModeConstants.ReturnClosestPoint);

                        while (fragScanIndexMatch < scanList.MasterScanOrderCount && scanList.MasterScanOrder[fragScanIndexMatch].ScanType == clsScanList.eScanTypeConstants.SurveyScan)
                        {
                            fragScanIndexMatch += 1;
                        }

                        if (fragScanIndexMatch == scanList.MasterScanOrderCount)
                        {
                            // Did not find the next frag scan; find the previous frag scan
                            fragScanIndexMatch -= 1;
                            while (fragScanIndexMatch > 0 && scanList.MasterScanOrder[fragScanIndexMatch].ScanType == clsScanList.eScanTypeConstants.SurveyScan)
                            {
                                fragScanIndexMatch -= 1;
                            }

                            if (fragScanIndexMatch < 0)
                            {
                                fragScanIndexMatch = 0;
                            }
                        }

                        // This is a custom SIC-based parent ion
                        // Prior to August 2014, we set .FragScanIndices(0) = 0, which made it appear that the fragmentation scan was the first MS2 spectrum in the dataset for all custom SICs
                        // This caused undesirable display results in MASIC browser, so we now set it to the next MS2 scan that occurs after the survey scan (parent scan)
                        if (scanList.MasterScanOrder[fragScanIndexMatch].ScanType == clsScanList.eScanTypeConstants.FragScan)
                        {
                            currentParentIon.FragScanIndices.Add(scanList.MasterScanOrder[fragScanIndexMatch].ScanIndexPointer);
                        }
                        else
                        {
                            currentParentIon.FragScanIndices.Add(0);
                        }
                    }

                    currentParentIon.CustomSICPeak                       = true;
                    currentParentIon.CustomSICPeakComment                = customMzSearchValue.Comment;
                    currentParentIon.CustomSICPeakMZToleranceDa          = customMzSearchValue.MZToleranceDa;
                    currentParentIon.CustomSICPeakScanOrAcqTimeTolerance = customMzSearchValue.ScanOrAcqTimeTolerance;

                    if (currentParentIon.CustomSICPeakMZToleranceDa < double.Epsilon)
                    {
                        if (sicToleranceIsPPM)
                        {
                            currentParentIon.CustomSICPeakMZToleranceDa = clsUtilities.PPMToMass(defaultSICTolerance, currentParentIon.MZ);
                        }
                        else
                        {
                            currentParentIon.CustomSICPeakMZToleranceDa = defaultSICTolerance;
                        }
                    }

                    if (currentParentIon.CustomSICPeakScanOrAcqTimeTolerance < float.Epsilon)
                    {
                        currentParentIon.CustomSICPeakScanOrAcqTimeTolerance = defaultScanOrAcqTimeTolerance;
                    }
                    else
                    {
                        scanOrAcqTimeSumForAveraging += currentParentIon.CustomSICPeakScanOrAcqTimeTolerance;
                        scanOrAcqTimeSumCount        += 1;
                    }

                    if (currentParentIon.SurveyScanIndex < scanList.SurveyScans.Count)
                    {
                        currentParentIon.OptimalPeakApexScanNumber =
                            scanList.SurveyScans[currentParentIon.SurveyScanIndex].ScanNumber;
                    }
                    else
                    {
                        currentParentIon.OptimalPeakApexScanNumber = 1;
                    }

                    currentParentIon.PeakApexOverrideParentIonIndex = -1;

                    scanList.ParentIons.Add(currentParentIon);
                }

                if (scanOrAcqTimeSumCount == CustomMZSearchValues.Count && scanOrAcqTimeSumForAveraging > 0)
                {
                    // All of the entries had a custom scan or acq time tolerance defined
                    // Update mScanOrAcqTimeTolerance to the average of the values
                    ScanOrAcqTimeTolerance = (float)(Math.Round(scanOrAcqTimeSumForAveraging / scanOrAcqTimeSumCount, 4));
                }
            }
            catch (Exception ex)
            {
                OnErrorEvent("Error in AddCustomSICValues", ex);
            }
        }
        /// <summary>
        /// Add the parent ion, or associate the fragmentation scan with an existing parent ion
        ///
        /// Checks to see if the parent ion specified by surveyScanIndex and parentIonMZ exists in .ParentIons()
        /// If mrmDaughterMZ is > 0, also considers that value when determining uniqueness
        ///
        /// If the parent ion entry already exists, adds an entry to .FragScanIndices()
        /// If it does not exist, adds a new entry to .ParentIons()
        /// </summary>
        /// <param name="scanList"></param>
        /// <param name="surveyScanIndex">
        /// If this is less than 0 the first MS2 scan(s) in the file occurred before we encountered a survey scan
        /// In this case, we cannot properly associate the fragmentation scan with a survey scan
        /// </param>
        /// <param name="parentIonMZ"></param>
        /// <param name="mrmDaughterMZ"></param>
        /// <param name="mrmToleranceHalfWidth"></param>
        /// <param name="fragScanIndex">This is typically equal to scanList.FragScans.Count - 1</param>
        /// <param name="spectraCache"></param>
        /// <param name="sicOptions"></param>
        private void AddUpdateParentIons(
            clsScanList scanList,
            int surveyScanIndex,
            double parentIonMZ,
            double mrmDaughterMZ,
            double mrmToleranceHalfWidth,
            int fragScanIndex,
            clsSpectraCache spectraCache,
            clsSICOptions sicOptions)
        {
            const double MINIMUM_TOLERANCE_PPM = 0.01;
            const double MINIMUM_TOLERANCE_DA  = 0.0001;

            var parentIonIndex = 0;

            double parentIonTolerance;

            if (sicOptions.SICToleranceIsPPM)
            {
                parentIonTolerance = sicOptions.SICTolerance / sicOptions.CompressToleranceDivisorForPPM;
                if (parentIonTolerance < MINIMUM_TOLERANCE_PPM)
                {
                    parentIonTolerance = MINIMUM_TOLERANCE_PPM;
                }
            }
            else
            {
                parentIonTolerance = sicOptions.SICTolerance / sicOptions.CompressToleranceDivisorForDa;
                if (parentIonTolerance < MINIMUM_TOLERANCE_DA)
                {
                    parentIonTolerance = MINIMUM_TOLERANCE_DA;
                }
            }

            // See if an entry exists yet in .ParentIons for the parent ion for this fragmentation scan
            var matchFound = false;

            if (mrmDaughterMZ > 0)
            {
                if (sicOptions.SICToleranceIsPPM)
                {
                    // Force the tolerances to 0.01 m/z units
                    parentIonTolerance = MINIMUM_TOLERANCE_PPM;
                }
                else
                {
                    // Force the tolerances to 0.01 m/z units
                    parentIonTolerance = MINIMUM_TOLERANCE_DA;
                }
            }

            if (parentIonMZ > 0)
            {
                var parentIonToleranceDa = GetParentIonToleranceDa(sicOptions, parentIonMZ, parentIonTolerance);

                for (parentIonIndex = scanList.ParentIons.Count - 1; parentIonIndex >= 0; parentIonIndex += -1)
                {
                    if (scanList.ParentIons[parentIonIndex].SurveyScanIndex >= surveyScanIndex)
                    {
                        if (Math.Abs(scanList.ParentIons[parentIonIndex].MZ - parentIonMZ) <= parentIonToleranceDa)
                        {
                            if (mrmDaughterMZ < double.Epsilon ||
                                Math.Abs(scanList.ParentIons[parentIonIndex].MRMDaughterMZ - mrmDaughterMZ) <= parentIonToleranceDa)
                            {
                                matchFound = true;
                                break;
                            }
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (!matchFound)
            {
                // Add a new parent ion entry to .ParentIons(), but only if surveyScanIndex is non-negative

                if (surveyScanIndex < 0)
                {
                    return;
                }

                var newParentIon = new clsParentIonInfo(parentIonMZ)
                {
                    SurveyScanIndex       = surveyScanIndex,
                    CustomSICPeak         = false,
                    MRMDaughterMZ         = mrmDaughterMZ,
                    MRMToleranceHalfWidth = mrmToleranceHalfWidth
                };

                newParentIon.FragScanIndices.Add(fragScanIndex);

                newParentIon.OptimalPeakApexScanNumber      = scanList.SurveyScans[surveyScanIndex].ScanNumber;   // Was: .FragScans(fragScanIndex).ScanNumber
                newParentIon.PeakApexOverrideParentIonIndex = -1;
                scanList.FragScans[fragScanIndex].FragScanInfo.ParentIonInfoIndex = scanList.ParentIons.Count;

                // Look for .MZ in the survey scan, using a tolerance of parentIonTolerance
                // If found, then update the mass to the matched ion
                // This is done to determine the parent ion mass more precisely
                if (sicOptions.RefineReportedParentIonMZ)
                {
                    if (FindClosestMZ(spectraCache, scanList.SurveyScans, surveyScanIndex, parentIonMZ, parentIonTolerance, out var parentIonMZMatch))
                    {
                        newParentIon.UpdateMz(parentIonMZMatch);
                    }
                }

                scanList.ParentIons.Add(newParentIon);
                return;
            }

            // Add a new entry to .FragScanIndices() for the matching parent ion
            // However, do not add a new entry if this is an MRM scan
            if (mrmDaughterMZ < double.Epsilon)
            {
                scanList.ParentIons[parentIonIndex].FragScanIndices.Add(fragScanIndex);
                scanList.FragScans[fragScanIndex].FragScanInfo.ParentIonInfoIndex = parentIonIndex;
            }
        }