Esempio n. 1
0
        /// <summary>
        /// Handle a single precursor element and child nodes
        /// Called by ReadPrecursorList (xml hierarchy)
        /// </summary>
        /// <param name="reader">XmlReader that is only valid for the scope of the single precursor element</param>
        /// <returns></returns>
        private Precursor ReadPrecursor(XmlReader reader)
        {
            reader.MoveToContent();
            reader.ReadStartElement("precursor"); // Throws exception if we are not at the "precursor" tag.
            XmlReader innerReader;
            Precursor precursor = new Precursor();
            while (reader.ReadState == ReadState.Interactive)
            {
                // Handle exiting out properly at EndElement tags
                if (reader.NodeType != XmlNodeType.Element)
                {
                    reader.Read();
                    continue;
                }

                switch (reader.Name)
                {
                    case "isolationWindow":
                        // Schema requirements: zero to one instances of this element
                        innerReader = reader.ReadSubtree();
                        innerReader.MoveToContent();
                        innerReader.ReadStartElement("isolationWindow"); // Throws exception if we are not at the "selectedIon" tag.
                        while (innerReader.ReadState == ReadState.Interactive)
                        {
                            // Handle exiting out properly at EndElement tags
                            if (innerReader.NodeType != XmlNodeType.Element)
                            {
                                innerReader.Read();
                                continue;
                            }
                            switch (innerReader.Name)
                            {
                                case "referenceableParamGroupRef":
                                    // Schema requirements: zero to many instances of this element
                                    innerReader.Skip();
                                    break;
                                case "cvParam":
                                    // Schema requirements: zero to many instances of this element
                                    /* MUST supply a *child* term of MS:1000792 (isolation window attribute) one or more times
                                     *   e.g.: MS:1000827 (isolation window target m/z)
                                     *   e.g.: MS:1000828 (isolation window lower offset)
                                     *   e.g.: MS:1000829 (isolation window upper offset)
                                     */
                                    switch (innerReader.GetAttribute("accession"))
                                    {
                                        case "MS:1000827":
                                            // name="isolation window target m/z"
                                            precursor.IsolationWindowTargetMz = Convert.ToDouble(innerReader.GetAttribute("value"));
                                            break;
                                        case "MS:1000828":
                                            // name="isolation window lower offset"
                                            precursor.IsolationWindowLowerOffset = Convert.ToDouble(innerReader.GetAttribute("value"));
                                            break;
                                        case "MS:1000829":
                                            // name="isolation window upper offset"
                                            precursor.IsolationWindowUpperOffset = Convert.ToDouble(innerReader.GetAttribute("value"));
                                            break;
                                    }
                                    innerReader.Read(); // Consume the cvParam element (no child nodes)
                                    break;
                                case "userParam":
                                    // Schema requirements: zero to many instances of this element
                                    innerReader.Skip();
                                    break;
                                default:
                                    innerReader.Skip();
                                    break;
                            }
                        }
                        innerReader.Close();
                        reader.Read(); // "selectedIon" might not have child nodes
                        // We will either consume the EndElement, or the same element that was passed to ReadSpectrum (in case of no child nodes)
                        break;
                    case "selectedIonList":
                        // Schema requirements: zero to one instances of this element
                        // mzML_1.0.0: one instance of this element
                        precursor.Ions = ReadSelectedIonList(reader.ReadSubtree());
                        reader.ReadEndElement(); // "selectedIonList" must have child nodes
                        break;
                    case "activation":
                        // Schema requirements: one instance of this element
                        innerReader = reader.ReadSubtree();
                        innerReader.MoveToContent();
                        innerReader.ReadStartElement("activation"); // Throws exception if we are not at the "activation" tag.
                        while (innerReader.ReadState == ReadState.Interactive)
                        {
                            // Handle exiting out properly at EndElement tags
                            if (innerReader.NodeType != XmlNodeType.Element)
                            {
                                innerReader.Read();
                                continue;
                            }
                            switch (innerReader.Name)
                            {
                                case "referenceableParamGroupRef":
                                    // Schema requirements: zero to many instances of this element
                                    innerReader.Skip();
                                    break;
                                case "cvParam":
                                    // Schema requirements: zero to many instances of this element
                                    /* MAY supply a *child* term of MS:1000510 (precursor activation attribute) one or more times
                                     *   e.g.: MS:1000045 (collision energy)
                                     *   e.g.: MS:1000138 (percent collision energy)
                                     *   e.g.: MS:1000245 (charge stripping)
                                     *   e.g.: MS:1000412 (buffer gas)
                                     *   e.g.: MS:1000419 (collision gas)
                                     *   e.g.: MS:1000509 (activation energy)
                                     *   e.g.: MS:1000869 (collision gas pressure)
                                     * MUST supply term MS:1000044 (dissociation method) or any of its children one or more times
                                     *   e.g.: MS:1000133 (collision-induced dissociation)
                                     *   e.g.: MS:1000134 (plasma desorption)
                                     *   e.g.: MS:1000135 (post-source decay)
                                     *   e.g.: MS:1000136 (surface-induced dissociation)
                                     *   e.g.: MS:1000242 (blackbody infrared radiative dissociation)
                                     *   e.g.: MS:1000250 (electron capture dissociation)
                                     *   e.g.: MS:1000262 (infrared multiphoton dissociation)
                                     *   e.g.: MS:1000282 (sustained off-resonance irradiation)
                                     *   e.g.: MS:1000422 (high-energy collision-induced dissociation)
                                     *   e.g.: MS:1000433 (low-energy collision-induced dissociation)
                                     *   et al.
                                     *   
                                     *   e.g.: MS:1000133 "collision-induced dissociation"
                                     *   e.g.: MS:1000134 "plasma desorption"
                                     *   e.g.: MS:1000135 "post-source decay"
                                     *   e.g.: MS:1000136 "surface-induced dissociation"
                                     *   e.g.: MS:1000242 "blackbody infrared radiative dissociation"
                                     *   e.g.: MS:1000250 "electron capture dissociation"
                                     *   e.g.: MS:1000262 "infrared multiphoton dissociation"
                                     *   e.g.: MS:1000282 "sustained off-resonance irradiation"
                                     *   e.g.: MS:1000422 "beam-type collision-induced dissociation"
                                     *   e.g.: MS:1000433 "low-energy collision-induced dissociation"
                                     *   e.g.: MS:1000435 "photodissociation"
                                     *   e.g.: MS:1000598 "electron transfer dissociation"
                                     *   e.g.: MS:1000599 "pulsed q dissociation"
                                     *   e.g.: MS:1001880 "in-source collision-induced dissociation"
                                     *   e.g.: MS:1002000 "LIFT"
                                     *   e.g.: MS:1002472 "trap-type collision-induced dissociation"
                                     */
                                    switch (innerReader.GetAttribute("accession"))
                                    {
                                        case "MS:1000133":
                                            // name="collision-induced dissociation"
                                            precursor.Activation = ActivationMethod.CID;
                                            break;
                                        case "MS:1000598":
                                            // name="electron transfer dissociation"
                                            precursor.Activation = ActivationMethod.ETD;
                                            break;
                                        case "MS:1000422":
                                            // name="beam-type collision-induced dissociation", "high-energy collision-induced dissociation"
                                            precursor.Activation = ActivationMethod.HCD;
                                            break;
                                        case "MS:1000250":
                                            // name="electron capture dissociation"
                                            precursor.Activation = ActivationMethod.ECD;
                                            break;
                                        case "MS:1000599":
                                            // name="pulsed q dissociation"
                                            precursor.Activation = ActivationMethod.PQD;
                                            break;
                                        case "MS:1000045":
                                            // name="collision energy"
                                            //energy = Convert.ToDouble(innerReader.GetAttribute("value"));
                                            break;
                                    }
                                    innerReader.Read(); // Consume the cvParam element (no child nodes)
                                    break;
                                case "userParam":
                                    // Schema requirements: zero to many instances of this element
                                    innerReader.Skip();
                                    break;
                                default:
                                    innerReader.Skip();
                                    break;
                            }
                        }
                        innerReader.Close();
                        reader.Read(); // "selectedIon" might not have child nodes
                        // We will either consume the EndElement, or the same element that was passed to ReadSpectrum (in case of no child nodes)
                        break;
                    default:
                        reader.Skip();
                        break;
                }
            }
            reader.Close();
            return precursor;
        }
Esempio n. 2
0
        /// <summary>
        /// Handle a single spectrum element and child nodes
        /// Called by ReadSpectrumList (xml hierarchy)
        /// </summary>
        /// <param name="reader">XmlReader that is only valid for the scope of the single spectrum element</param>
        /// <param name="includePeaks">Whether to read binary data arrays</param>
        private Spectrum ReadSpectrum(XmlReader reader, bool includePeaks = true)
        {
            reader.MoveToContent();
            string index = reader.GetAttribute("index");
            //Console.WriteLine("Reading spectrum indexed by " + index);
            // This is correct for Thermo files converted by msConvert, but need to implement for others as well
            string spectrumId = reader.GetAttribute("id"); // Native ID in mzML_1.1.0; unique identifier in mzML_1.0.0, often same as nativeID
            string nativeId = spectrumId;
            if (_version == MzML_Version.mzML1_0_0)
            {
                nativeId = reader.GetAttribute("nativeID"); // Native ID in mzML_1.0.0
            }

            int scanNum = -1;
            // If a random access reader, there is already a scan number stored, based on the order of the index. Use it instead.
            if (_randomAccess)
            {
                scanNum = (int) (_spectrumOffsets.NativeToIdMap[nativeId]);
            }
            else
            {
                scanNum = (int)(_artificialScanNum++);
                // Interpret the NativeID (if the format has an interpreter) and use it instead of the artificial number.
                // TODO: Better handling than the artificial ID for other nativeIDs (ones currently not supported)
                int num = 0;
                if (NativeIdConversion.TryGetScanNumberInt(nativeId, out num))
                {
                    scanNum = num;
                }
            }

            int defaultArraySize = Convert.ToInt32(reader.GetAttribute("defaultArrayLength"));
            reader.ReadStartElement("spectrum"); // Throws exception if we are not at the "spectrum" tag.
            bool is_ms_ms = false;
            int msLevel = 0;
            bool centroided = false;
            double tic = 0;
            List<Precursor> precursors = new List<Precursor>();
            List<ScanData> scans = new List<ScanData>();
            List<BinaryDataArray> bdas = new List<BinaryDataArray>();
            while (reader.ReadState == ReadState.Interactive)
            {
                // Handle exiting out properly at EndElement tags
                if (reader.NodeType != XmlNodeType.Element)
                {
                    reader.Read();
                    continue;
                }
                //////////////////////////////////////////////////////////////////////////////////////
                /// 
                /// MS1 Spectra: only need Spectrum data: scanNum, MSLevel, ElutionTime, mzArray, IntensityArray
                /// 
                /// MS2 Spectra: use ProductSpectrum; adds ActivationMethod and IsolationWindow
                /// 
                //////////////////////////////////////////////////////////////////////////////////////
                switch (reader.Name)
                {
                    case "referenceableParamGroupRef":
                        // Schema requirements: zero to many instances of this element
                        reader.Skip();
                        break;
                    case "cvParam":
                        // Schema requirements: zero to many instances of this element
                        /* MAY supply a *child* term of MS:1000465 (scan polarity) only once
                         *   e.g.: MS:1000129 (negative scan)
                         *   e.g.: MS:1000130 (positive scan)
                         * MUST supply a *child* term of MS:1000559 (spectrum type) only once
                         *   e.g.: MS:1000322 (charge inversion mass spectrum)
                         *   e.g.: MS:1000325 (constant neutral gain spectrum)
                         *   e.g.: MS:1000326 (constant neutral loss spectrum)
                         *   e.g.: MS:1000328 (e/2 mass spectrum)
                         *   e.g.: MS:1000341 (precursor ion spectrum)
                         *   e.g.: MS:1000579 (MS1 spectrum)
                         *   e.g.: MS:1000580 (MSn spectrum)
                         *   e.g.: MS:1000581 (CRM spectrum)
                         *   e.g.: MS:1000582 (SIM spectrum)
                         *   e.g.: MS:1000583 (SRM spectrum)
                         *   e.g.: MS:1000620 (PDA spectrum)
                         *   e.g.: MS:1000627 (selected ion current chromatogram)
                         *   e.g.: MS:1000789 (enhanced multiply charged spectrum)
                         *   e.g.: MS:1000790 (time-delayed fragmentation spectrum)
                         *   et al.
                         * MUST supply term MS:1000525 (spectrum representation) or any of its children only once
                         *   e.g.: MS:1000127 (centroid spectrum)
                         *   e.g.: MS:1000128 (profile spectrum)
                         * MAY supply a *child* term of MS:1000499 (spectrum attribute) one or more times
                         *   e.g.: MS:1000285 (total ion current)
                         *   e.g.: MS:1000497 (zoom scan)
                         *   e.g.: MS:1000504 (base peak m/z)
                         *   e.g.: MS:1000505 (base peak intensity)
                         *   e.g.: MS:1000511 (ms level)
                         *   e.g.: MS:1000527 (highest observed m/z)
                         *   e.g.: MS:1000528 (lowest observed m/z)
                         *   e.g.: MS:1000618 (highest observed wavelength)
                         *   e.g.: MS:1000619 (lowest observed wavelength)
                         *   e.g.: MS:1000796 (spectrum title)
                         *   et al.
                         */
                        switch (reader.GetAttribute("accession"))
                        {
                            case "MS:1000127":
                                // name="centroid spectrum"
                                centroided = true;
                                break;
                            case "MS:1000128":
                                // name="profile spectrum"
                                centroided = false;
                                break;
                            case "MS:1000511":
                                // name="ms level"
                                msLevel = Convert.ToInt32(reader.GetAttribute("value"));
                                break;
                            case "MS:1000579":
                                // name="MS1 spectrum"
                                is_ms_ms = false;
                                break;
                            case "MS:1000580":
                                // name="MSn spectrum"
                                is_ms_ms = true;
                                break;
                            case "MS:1000285":
                                // name="total ion current"
                                tic = Convert.ToDouble(reader.GetAttribute("value"));
                                break;
                        }
                        reader.Read(); // Consume the cvParam element (no child nodes)
                        break;
                    case "userParam":
                        // Schema requirements: zero to many instances of this element
                        reader.Skip();
                        break;
                    case "spectrumDescription": // mzML_1.0.0 compatibility
                        // Schema requirements: one instance of this element
                        ReadSpectrumDescription(reader.ReadSubtree(), ref scans, ref precursors, out centroided);
                        reader.ReadEndElement(); // "spectrumDescription" must have child nodes
                        break;
                    case "scanList":
                        // Schema requirements: zero to one instances of this element
                        scans.AddRange(ReadScanList(reader.ReadSubtree()));
                        reader.ReadEndElement(); // "scanList" must have child nodes
                        break;
                    case "precursorList":
                        // Schema requirements: zero to one instances of this element
                        precursors.AddRange(ReadPrecursorList(reader.ReadSubtree()));
                        reader.ReadEndElement(); // "precursorList" must have child nodes
                        break;
                    case "productList":
                        // Schema requirements: zero to one instances of this element
                        reader.Skip();
                        break;
                    case "binaryDataArrayList":
                        // Schema requirements: zero to one instances of this element
                        if (includePeaks)
                        {
                            bdas.AddRange(ReadBinaryDataArrayList(reader.ReadSubtree(), defaultArraySize));
                            reader.ReadEndElement(); // "binaryDataArrayList" must have child nodes
                        }
                        else
                        {
                            reader.Skip();
                        }
                        break;
                    default:
                        reader.Skip();
                        break;
                }
            }
            reader.Close();
            // Process the spectrum data
            ScanData scan = new ScanData();
            Spectrum spectrum;
            BinaryDataArray mzs = new BinaryDataArray();
            BinaryDataArray intensities = new BinaryDataArray();
            foreach (var bda in bdas)
            {
                if (bda.ArrayType == ArrayType.m_z_array)
                {
                    mzs = bda;
                }
                else if (bda.ArrayType == ArrayType.intensity_array)
                {
                    intensities = bda;
                }
            }
            
            if (!centroided && includePeaks)
            {
                // Centroid spectrum
                // ProteoWizard
                var centroider = new Centroider(mzs.Data, intensities.Data);
                double[] centroidedMzs, centroidedIntensities;
                centroider.GetCentroidedData(out centroidedMzs, out centroidedIntensities);
                mzs.Data = centroidedMzs;
                intensities.Data = centroidedIntensities;
            }
            if (scans.Count == 1)
            {
                scan = scans[0];
            }
            else if (scans.Count > 1)
            {
                // TODO: Should do something else to appropriately handle combinations...
                scan = scans[0];
            }

            if (is_ms_ms)
            {
                Precursor precursor = new Precursor();
                if (precursors.Count == 1)
                {
                    precursor = precursors[0];
                }
                else if (precursors.Count > 1)
                {
                    // TODO: Should do something else to appropriately handle multiple precursors...
                    precursor = precursors[0];
                }
                SelectedIon ion = new SelectedIon();
                if (precursor.Ions.Count == 1)
                {
                    ion = precursor.Ions[0];
                }
                else if (precursor.Ions.Count > 1)
                {
                    // TODO: Should do something else to appropriately handle multiple selected ions...
                    ion = precursor.Ions[0];
                }

                var pspectrum = new ProductSpectrum(mzs.Data, intensities.Data, scanNum);
                pspectrum.ActivationMethod = precursor.Activation;
                // Select mz value to use based on presence of a Thermo-specific user param.
                // The user param has a slightly higher precision, if that matters.
                double mz = scan.MonoisotopicMz == 0.0 ? ion.SelectedIonMz : scan.MonoisotopicMz;
                pspectrum.IsolationWindow = new IsolationWindow(precursor.IsolationWindowTargetMz, precursor.IsolationWindowLowerOffset, precursor.IsolationWindowUpperOffset, mz, ion.Charge);
                //pspectrum.IsolationWindow.OldCharge = ion.OldCharge;
                //pspectrum.IsolationWindow.SelectedIonMz = ion.SelectedIonMz;
                spectrum = pspectrum;
            }
            else
            {
                spectrum = new Spectrum(mzs.Data, intensities.Data, scanNum);
            }
            spectrum.MsLevel = msLevel;
            spectrum.ElutionTime = scan.StartTime;
            spectrum.NativeId = nativeId;
            spectrum.TotalIonCurrent = tic;
            
            return spectrum;
        }