public void DetermineMRMScanType(string filterText, MRMScanTypeConstants expectedResult)
        {
            var mrmScanType = XRawFileIO.DetermineMRMScanType(filterText);

            Console.WriteLine(filterText + " " + mrmScanType);

            Assert.AreEqual(expectedResult, mrmScanType);
        }
        /// <summary>
        /// Parse out the MRM_QMS or SRM mass info from filterText
        /// </summary>
        /// <param name="filterText"></param>
        /// <param name="mrmScanType"></param>
        /// <param name="mrmInfo">Output: MRM info class</param>
        /// <remarks>We do not parse mass information out for Full Neutral Loss scans</remarks>
        public static void ExtractMRMMasses(string filterText, MRMScanTypeConstants mrmScanType, out MRMInfo mrmInfo)
        {
            // Parse out the MRM_QMS or SRM mass info from filterText
            // It should be of the form

            // SIM:              p NSI SIM ms [330.00-380.00]
            // or
            // MRM_Q1MS_TEXT:    p NSI Q1MS [179.652-184.582, 505.778-510.708, 994.968-999.898]
            // or
            // MRM_Q3MS_TEXT:    p NSI Q3MS [150.070-1500.000]
            // or
            // MRM_SRM_TEXT:     c NSI SRM ms2 [email protected] [397.209-392.211, 579.289-579.291]

            // Note: we do not parse mass information out for Full Neutral Loss scans
            // MRM_FullNL_TEXT: c NSI Full cnl 162.053 [300.000-1200.000]

            mrmInfo = new MRMInfo();

            if (string.IsNullOrWhiteSpace(filterText))
            {
                return;
            }

            if (!(mrmScanType == MRMScanTypeConstants.SIM |
                  mrmScanType == MRMScanTypeConstants.MRMQMS |
                  mrmScanType == MRMScanTypeConstants.SRM))
            {
                // Unsupported MRM type
                return;
            }

            // Parse out the text between the square brackets
            var reMatch = mMassList.Match(filterText);

            if (!reMatch.Success)
            {
                return;
            }

            reMatch = mMassRanges.Match(reMatch.Value);

            while (reMatch.Success)
            {
                try
                {
                    // Note that group 0 is the full mass range (two mass values, separated by a dash)
                    // Group 1 is the first mass value
                    // Group 2 is the second mass value

                    var mrmMassRange = new udtMRMMassRangeType
                    {
                        StartMass = double.Parse(reMatch.Groups["StartMass"].Value),
                        EndMass = double.Parse(reMatch.Groups["EndMass"].Value)
                    };

                    var centralMass = mrmMassRange.StartMass + (mrmMassRange.EndMass - mrmMassRange.StartMass) / 2;
                    mrmMassRange.CentralMass = Math.Round(centralMass, 6);

                    mrmInfo.MRMMassList.Add(mrmMassRange);

                }
                catch (Exception)
                {
                    // Error parsing out the mass values; skip this group
                }

                reMatch = reMatch.NextMatch();
            }
        }
        /// <summary>
        /// Examines filterText to validate that it is a supported MS1 scan type (MS, SIM, or MRMQMS, or SRM scan)
        /// </summary>
        /// <param name="filterText"></param>
        /// <param name="msLevel"></param>
        /// <param name="simScan">True if mrmScanType is SIM or MRMQMS</param>
        /// <param name="mrmScanType"></param>
        /// <param name="zoomScan"></param>
        /// <returns>True if filterText contains a known MS scan type</returns>
        /// <remarks>Returns false for MSn scans (like ms2 or ms3)</remarks>
        public static bool ValidateMSScan(
            string filterText,
            out int msLevel,
            out bool simScan,
            out MRMScanTypeConstants mrmScanType,
            out bool zoomScan)
        {
            simScan = false;
            mrmScanType = MRMScanTypeConstants.NotMRM;
            zoomScan = false;

            var ms1Tags = new List<string> {
                FULL_MS_TEXT,
                MS_ONLY_C_TEXT,
                MS_ONLY_P_TEXT,
                MS_ONLY_P_NSI_TEXT,
                FULL_PR_TEXT,
                FULL_LOCK_MS_TEXT
            };

            var zoomTags = new List<string> {
                MS_ONLY_Z_TEXT,
                MS_ONLY_PZ_TEXT,
                MS_ONLY_DZ_TEXT
            };

            if (ContainsAny(filterText, ms1Tags, 1))
            {
                // This is a Full MS scan
                msLevel = 1;
                return true;
            }

            if (ContainsAny(filterText, zoomTags, 1))
            {
                msLevel = 1;
                zoomScan = true;
                return true;
            }

            if (ContainsText(filterText, MS_ONLY_PZ_MS2_TEXT, 1))
            {
                // Technically, this should have MSLevel = 2, but that would cause a bunch of problems elsewhere in MASIC
                // Thus, we'll pretend it's MS1
                msLevel = 1;
                zoomScan = true;
                return true;
            }

            mrmScanType = DetermineMRMScanType(filterText);
            switch (mrmScanType)
            {
                case MRMScanTypeConstants.SIM:
                    // Selected ion monitoring, which is MS1 of a narrow m/z range
                    msLevel = 1;
                    simScan = true;
                    return true;
                case MRMScanTypeConstants.MRMQMS:
                    // Multiple SIM ranges in a single scan
                    msLevel = 1;
                    simScan = true;
                    return true;
                case MRMScanTypeConstants.SRM:
                    msLevel = 2;
                    return true;
                case MRMScanTypeConstants.FullNL:
                    msLevel = 2;
                    return true;
                default:
                    string mzText;
                    ExtractMSLevel(filterText, out msLevel, out mzText);
                    return false;
            }
        }
        public void ValidateMSScan(
            string filterText,
            bool expectedIsValidMS1orSIM,
            int expectedMSLevel,
            bool expectedIsSIMScan,
            MRMScanTypeConstants expectedMRMScanType,
            bool expectedIsZoomScan)
        {
            int msLevel;
            bool isSIMScan;
            MRMScanTypeConstants mrmScanType;
            bool zoomScan;

            var isValid = XRawFileIO.ValidateMSScan(filterText, out msLevel, out isSIMScan, out mrmScanType, out zoomScan);

            Console.WriteLine(filterText + "  -- ms" + msLevel + "; SIM=" + isSIMScan + "; MRMScanType=" + mrmScanType);

            Assert.AreEqual(expectedIsValidMS1orSIM, isValid, "Mismatch for IsValidMS1orSIM");
            Assert.AreEqual(expectedMSLevel, msLevel, "MSLevel mismatch");
            Assert.AreEqual(expectedIsSIMScan, isSIMScan, "SIMScan mismatch");
            Assert.AreEqual(expectedMRMScanType, mrmScanType, "MRMScanType mismatch");
            Assert.AreEqual(expectedIsZoomScan, zoomScan, "ZoomScan mismatch");
        }