Esempio n. 1
0
 public Dictionary <string, dynamic> AssembleMetrics()
 {
     return(new Dictionary <string, dynamic>
     {
         { "QC:4000053", RTDuration },
         { "QC:02", swathSizeDifference },
         { "QC:4000059", Run.Ms1Scans.Count() },
         { "QC:4000060", Run.Ms2Scans.Count() },
         { "QC:04", SwathMetrics.swathTargets.Count() },
         { "QC:05", SwathMetrics.swathTargets },
         { "QC:06", Density.Sum() },
         { "QC:07", Density.ElementAt(Density.Count() / 2) },
         { "QC:08", InterQuartileRangeCalculator.CalcIQR(Density) },
         { "QC:09", SwathMetrics.numOfSwathPerGroup },
         { "QC:10", SwathMetrics.mzRange },
         { "QC:11", SwathMetrics.SwathProportionOfTotalTIC },
         { "QC:12", SwathMetrics.swDensity50 },
         { "QC:13", SwathMetrics.swDensityIQR },
         { "QC:14", RtMetrics.Peakwidths },
         { "QC:15", RtMetrics.PeakCapacity },
         { "QC:16", RtMetrics.MS1PeakPrecision },
         { "QC:17", RtMetrics.TicChange50List },
         { "QC:18", RtMetrics.TicChangeIqrList },
         { "QC:19", RtMetrics.CycleTime },
         { "QC:20", RtMetrics.MS2Density },
         { "QC:21", RtMetrics.MS1Density },
         { "QC:22", RtMetrics.MS2TicTotal },
         { "QC:23", RtMetrics.MS1TicTotal },
         { "QC:24", RtMetrics.TailingFactor }
     });
 }
Esempio n. 2
0
        public SwathMetrics GroupBySwath(Run <Scan> run)
        {
            //Create list of target isolationwindows to serve as swathnumber
            List <double> swathTargets = new List <double>();

            // Force ordering of swathTargets so that our tests don't depend on the order that Distinct() happens to impose.
            swathTargets = run.Ms2Scans.Select(x => x.IsolationWindowTargetMz).Distinct().OrderBy(x => x).ToList();
            double totalTIC = 0;

            foreach (var scan in run.Ms2Scans)
            {
                totalTIC += scan.TotalIonCurrent;
            }

            //Loop through every swath of a certain swathNumber:

            List <int>     numOfSwathPerGroup = new List <int>();
            List <double>  TICs                      = new List <double>();
            List <double>  swDensity                 = new List <double>();
            List <double>  swDensity50               = new List <double>();
            List <double?> swDensityIQR              = new List <double?>();
            List <double>  mzTargetRange             = new List <double>();
            List <double>  averageMzTargetRange      = new List <double>();
            List <double>  SwathProportionOfTotalTIC = new List <double>();
            List <double>  TotalSwathProportionPredictedSingleCharge = new List <double>();
            List <double>  SwathProportionPredictedSingleChargeAvg   = new List <double>();

//Loop through all the swaths of the same number and add to
            for (int swathNumber = 0; swathNumber < swathTargets.Count(); swathNumber++)
            {
                int track = 0;

                double TICthisSwath = 0;

                var orderedMS2Scans = run.Ms2Scans
                                      .Where(x => x.IsolationWindowTargetMz == swathTargets[swathNumber]); // Turns out ordering is not required; users of this either don't care about order or sort their own results.
                foreach (var scan in orderedMS2Scans)
                {
                    mzTargetRange.Add(scan.IsolationWindowUpperOffset + scan.IsolationWindowLowerOffset);
                    TICthisSwath += scan.TotalIonCurrent;
                    swDensity.Add(scan.Density);
                    TotalSwathProportionPredictedSingleCharge.Add(scan.ProportionChargeStateOne); //The chargestate one's we pick up is where there is a match for M+1. Therefore we need to double it to add the M.
                    track++;
                }
                averageMzTargetRange.Add(mzTargetRange.Average());
                numOfSwathPerGroup.Add(track);
                TICs.Add(TICthisSwath);
                TICthisSwath = 0;
                SwathProportionPredictedSingleChargeAvg.Add(TotalSwathProportionPredictedSingleCharge.Average());
                TotalSwathProportionPredictedSingleCharge.Clear();
                swDensity.Sort();
                swDensity50.Add(Math.Truncate(Math.Ceiling(swDensity.Average())));
                if (swDensity.Count > 4)
                {
                    swDensityIQR.Add(Math.Ceiling(InterQuartileRangeCalculator.CalcIQR(swDensity)));
                }
                else
                {
                    swDensityIQR.Add(default);
Esempio n. 3
0
        public RTMetrics DivideByRT(MzmlParser.Run run, int division, double rtDuration)
        {
            double rtSegment = rtDuration / division;

            rtSegs = new double[division];
            List <string> segmentBoundaries = new List <string>();

            for (int i = 0; i < division; i++)
            {
                rtSegs[i] = run.StartTime + rtSegment * i;
                if (i > 0)
                {
                    segmentBoundaries.Add(rtSegs[i - 1] + "_" + rtSegs[i]);//segmentBoundaries is a string denoting the startOfTheRTsegment_endOfTheRTsegment for reference
                }
                else
                {
                    segmentBoundaries.Add(run.StartTime + "_" + rtSegs[i]);
                }
            }

            //dividing basepeaks into segments
            foreach (MzmlParser.BasePeak basepeak in run.BasePeaks)
            {
                //Check to see in which RTsegment this basepeak is:
                foreach (double rt in basepeak.BpkRTs)
                {
                    if (rt > rtSegs.Last())
                    {
                        basepeak.RTsegments.Add(rtSegs.Count() - 1);
                    }
                    else if (rtSegs.Count() > 1 && rt < rtSegs[1])
                    {
                        basepeak.RTsegments.Add(0);
                    }
                    else
                    {
                        for (int segmentboundary = 2; segmentboundary < rtSegs.Count(); segmentboundary++)
                        {
                            if (rt > rtSegs[segmentboundary - 1] && rt < rtSegs[segmentboundary])
                            {
                                basepeak.RTsegments.Add(segmentboundary - 1);
                                segmentboundary = rtSegs.Count();//move to the next bpkRT
                            }
                        }
                    }
                }
            }
            double experimentWideMS2TICSquared = 0;

            //dividing ms2scans into segments of RT
            foreach (MzmlParser.Scan scan in run.Ms2Scans)
            {
                //if the scan starttime falls into the rtsegment, give it the correct rtsegment number
                //We assign to the segmentdivider below. So if >a and <b, it is assigned to segment a.

                if (scan.ScanStartTime > rtSegs.Last())//If the scan is after the last segment divider, it falls into the last segment
                {
                    scan.RTsegment = rtSegs.Count() - 1;
                }
                else if (rtSegs.Count() > 1 && scan.ScanStartTime < rtSegs[1])//If the scan is before the second segment divider it should fall in the first segment. (assuming that the user has selected to have more than one segment)
                {
                    scan.RTsegment = 0;
                }
                else
                {
                    for (int segmentboundary = 2; segmentboundary < rtSegs.Count(); segmentboundary++)                        //If the scan is not in the first or last segment
                    {
                        if (scan.ScanStartTime > rtSegs[segmentboundary - 1] && scan.ScanStartTime < rtSegs[segmentboundary]) // If the scan is larger than the previous boundary and smaller than this boundary, assign to the previous segment.
                        {
                            scan.RTsegment = segmentboundary - 1;
                        }
                    }
                }
                experimentWideMS2TICSquared += Math.Pow(scan.TotalIonCurrent, 2);
            }

            //dividing ms1scans into segments of RT
            foreach (MzmlParser.Scan scan in run.Ms1Scans)
            {
                if (scan.ScanStartTime > rtSegs.Last())//If the scan is after the last segment divider, it falls into the last segment
                {
                    scan.RTsegment = rtSegs.Count() - 1;
                }
                else if (rtSegs.Count() > 1 && scan.ScanStartTime < rtSegs[1])//If the scan is before the second segment divider it should fall in the first segment. (assuming that the user has selected to have more than one segment)
                {
                    scan.RTsegment = 0;
                }
                else
                {
                    for (int segmentboundary = 2; segmentboundary < rtSegs.Count(); segmentboundary++)                        //If the scan is not in the first or last segment
                    {
                        if (scan.ScanStartTime > rtSegs[segmentboundary - 1] && scan.ScanStartTime < rtSegs[segmentboundary]) // If the scan is larger than the previous boundary and smaller than this boundary, assign to the previous segment.
                        {
                            scan.RTsegment = segmentboundary - 1;
                        }
                    }
                }
            }

            //Retrieve TICChange metrics and divide into rtsegs
            List <double> ticChange50List  = new List <double>();
            List <double> ticChangeIqrList = new List <double>();
            var           tempTic          = run.Ms2Scans.OrderBy(x => x.ScanStartTime).GroupBy(x => x.RTsegment).Select(d => d.Select(g => g.TotalIonCurrent).ToList());
            double        magnitude        = Math.Pow(experimentWideMS2TICSquared, 0.5);

            for (int i = 0; i < tempTic.Count(); i++)
            {
                var           temp     = tempTic.ElementAt(i);
                List <double> tempList = new List <double>();
                for (int j = 1; j < temp.Count(); j++)
                {
                    tempList.Add(Math.Abs(temp.ElementAt(j) - temp.ElementAt(j - 1)) / magnitude);//Normalised to TIC magnitude.
                }
                tempList.Sort();
                ticChange50List.Add(tempList.Average());
                if (tempList.Count() > 4)
                {
                    ticChangeIqrList.Add(InterQuartileRangeCalculator.CalcIQR(tempList));
                }
                else
                {
                    logger.Error("There are only {0} MS2Scans in this segment, which is too few to calculate the IQR of the TIC Change. This value has been set to zero.", tempTic.Count());
                    ticChangeIqrList.Add(0);
                }
            }

            //Calculations for peakprecision MS2:

            var meanIntensityOfAllBpks = run.BasePeaks.Select(x => x.Intensities.Sum()).Average();
            var meanMzOfAllBpks        = run.BasePeaks.Select(x => x.Mz).Average();

            //Calculations for peakprecision MS1:
            //double mIMS1Bpks;
            //if (run.Ms1Scans.Count()>0) mIMS1Bpks = run.Ms1Scans.Select(x => x.BasePeakIntensity).Average();
            //var mMMS1Bpks = run.Ms1Scans.Select(x => x.BasePeakMz).Average();
            List <double> peakWidths       = new List <double>();
            List <double> TailingFactor    = new List <double>();
            List <double> peakCapacity     = new List <double>();
            List <double> peakPrecision    = new List <double>();
            List <double> ms1PeakPrecision = new List <double>();
            List <int>    ms1Density       = new List <int>();
            List <int>    ms2Density       = new List <int>();
            List <double> cycleTime        = new List <double>();
            List <double> ms1TicTotal      = new List <double>();
            List <double> Ms2TicTotal      = new List <double>();

            for (int segment = 0; segment < division; segment++)
            {
                List <double> peakWidthsTemp         = new List <double>();
                List <double> peakSymTemp            = new List <double>();
                List <double> fullWidthBaselinesTemp = new List <double>();
                List <double> peakPrecisionTemp      = new List <double>();
                foreach (MzmlParser.BasePeak basepeak in run.BasePeaks)
                {
                    for (int i = 0; i < basepeak.RTsegments.Count(); i++)
                    {
                        if (basepeak.RTsegments[i] == segment)
                        {
                            peakWidthsTemp.Add(basepeak.FWHMs[i]);
                            peakSymTemp.Add(basepeak.Peaksyms[i]);
                            peakPrecisionTemp.Add(basepeak.Intensities[i] / (meanIntensityOfAllBpks * Math.Pow(2, meanMzOfAllBpks / basepeak.Mz)));
                            fullWidthBaselinesTemp.Add(basepeak.FullWidthBaselines[i]);
                        }
                    }
                }

                List <double> firstScansOfCycle    = new List <double>();
                List <double> lastScansOfCycle     = new List <double>();
                List <double> difference           = new List <double>();
                double        ms1TicTotalTemp      = 0;
                List <int>    ms1DensityTemp       = new List <int>();
                List <double> ms1PeakPrecisionTemp = new List <double>();

                foreach (MzmlParser.Scan scan in run.Ms1Scans.OrderBy(x => x.ScanStartTime))
                {
                    if (scan.RTsegment == segment)
                    {
                        ms1PeakPrecisionTemp.Add(scan.BasePeakIntensity / (meanIntensityOfAllBpks * Math.Pow(2, meanMzOfAllBpks / scan.BasePeakMz)));
                        ms1DensityTemp.Add(scan.Density);
                        ms1TicTotalTemp += scan.TotalIonCurrent;
                    }
                }
                int minNumberMS1Or2 = 0;
                //To get scan speed for both ms1 and ms2 we have to also scan through ms2:
                if (run.Ms1Scans.Count() > 1)
                {
                    lastScansOfCycle  = run.Ms2Scans.Where(x => x.RTsegment == segment).GroupBy(g => g.Cycle).Select(x => x.Max(y => y.ScanStartTime)).ToList();
                    firstScansOfCycle = run.Ms1Scans.Where(x => x.RTsegment == segment).Select(y => y.ScanStartTime).ToList();
                }
                else
                {
                    lastScansOfCycle  = run.Ms2Scans.Where(x => x.RTsegment == segment).GroupBy(g => g.Cycle).Select(x => x.Max(y => y.ScanStartTime)).ToList();
                    firstScansOfCycle = run.Ms2Scans.Where(x => x.RTsegment == segment).GroupBy(g => g.Cycle).Select(x => x.Min(y => y.ScanStartTime)).ToList();
                }
                minNumberMS1Or2 = Math.Min(lastScansOfCycle.Count(), firstScansOfCycle.Count());
                for (int i = 0; i < minNumberMS1Or2; i++)
                {
                    difference.Add(lastScansOfCycle[i] - firstScansOfCycle[i]);
                }
                cycleTime.Add(difference.Average() * 60);
                List <int> ms2DensityTemp  = run.Ms2Scans.Where(x => x.RTsegment == segment).Select(x => x.Density).ToList();
                double     ms2TicTotalTemp = run.Ms2Scans.Where(x => x.RTsegment == segment).Select(x => x.TotalIonCurrent).Sum();

                if (peakWidthsTemp.Count > 0)
                {
                    peakWidths.Add(peakWidthsTemp.Average());
                    TailingFactor.Add(peakSymTemp.Average());
                    peakCapacity.Add(rtSegment / fullWidthBaselinesTemp.Average());//PeakCapacity is calculated as per Dolan et al.,2009, PubMed 10536823);
                    peakPrecision.Add(peakPrecisionTemp.Average());
                }
                else
                {
                    peakWidths.Add(0);
                    TailingFactor.Add(0);
                    peakCapacity.Add(0);
                    peakPrecision.Add(0);
                }
                if (ms1PeakPrecisionTemp.Count > 0)
                {
                    ms1PeakPrecision.Add(ms1PeakPrecisionTemp.Average());
                    ms1Density.Add(Convert.ToInt32(Math.Ceiling(ms1DensityTemp.Average())));
                }
                else
                {
                    ms1PeakPrecision.Add(0);
                    ms1Density.Add(0);
                }
                ms2Density.Add(Convert.ToInt32(Math.Round(ms2DensityTemp.Average(), 0)));
                ms1TicTotal.Add(ms1TicTotalTemp);
                Ms2TicTotal.Add(ms2TicTotalTemp);
            }

            RTMetrics rtMetrics = new RTMetrics(ms1TicTotal, Ms2TicTotal, cycleTime, ticChange50List, ticChangeIqrList, ms1Density, ms2Density, peakWidths, TailingFactor, peakCapacity, peakPrecision, ms1PeakPrecision, segmentBoundaries);

            return(rtMetrics);
        }
Esempio n. 4
0
        public Dictionary <string, dynamic> GenerateMetrics(Run run, int division, string inputFilePath, bool irt, bool combine, bool lastFile, string date)
        {
            Run = run;
            if (run.LastScanTime != 0 && run.StartTime != 1000000)
            {
                //Acquire RTDuration: last minus first
                RTDuration = run.LastScanTime - run.StartTime;
            }
            else
            {
                Logger.Error("StartTime {0} or lastScanTime {0} for the run is null. RTDuration is therefore zero", run.StartTime, run.LastScanTime);
                RTDuration = 0;
            }


            //Interpolate, Smooth, create chromatogram and generate chromatogram metrics
            ChromatogramMetricGenerator chromatogramMetrics = new ChromatogramMetricGenerator();

            chromatogramMetrics.GenerateChromatogram(run);

            if (irt)
            {
                chromatogramMetrics.GenerateiRTChromatogram(run);
            }

            //Calculating the largestswath
            if (run.Ms2Scans.Max(x => x.IsolationWindowUpperOffset) == 100000 || run.Ms2Scans.Max(x => x.IsolationWindowLowerOffset) == 100000)
            {
                Logger.Error(("IsolationWindowUpperOffset {0} or IsolationWindowLowerOffset {0} for the one of the scans has not been changed from default value. swathSizeDifference is therefore zero", run.Ms2Scans.Max(x => x.IsolationWindowUpperOffset), run.Ms2Scans.Max(x => x.IsolationWindowLowerOffset)));
                swathSizeDifference = 0;
            }
            else
            {
                swathSizeDifference = run.Ms2Scans.Max(x => x.IsolationWindowUpperOffset + x.IsolationWindowLowerOffset) - run.Ms2Scans.Min(x => x.IsolationWindowUpperOffset + x.IsolationWindowLowerOffset);
            }

            // This method will group the scans into swaths of the same number, return the number of swaths in a full cycle (maxswath) and call a FileMaker method to write out the metrics.
            SwathGrouper swathGrouper = new SwathGrouper {
            };

            SwathMetrics = swathGrouper.GroupBySwath(run);

            //Retrieving Density metrics
            Density = run.Ms2Scans.OrderBy(g => g.Density).Select(g => g.Density).ToList();


            RTGrouper rtGrouper = new RTGrouper {
            };

            RtMetrics = rtGrouper.DivideByRT(run, division, RTDuration);
            FileMaker fileMaker = new FileMaker(division, inputFilePath, run, SwathMetrics, RtMetrics, RTDuration, swathSizeDifference, run.Ms2Scans.Count(), Density.Sum(), Density.ElementAt(Density.Count() / 2), InterQuartileRangeCalculator.CalcIQR(Density), run.Ms1Scans.Count(), date);

            fileMaker.MakeComprehensiveMetricsFile();
            if (run.IRTPeaks != null && run.IRTPeaks.Count() > 0)
            {
                fileMaker.MakeiRTmetricsFile(run);
            }

            fileMaker.MakeMetricsPerRTsegmentFile(RtMetrics);
            fileMaker.MakeMetricsPerSwathFile(SwathMetrics);

            if (combine && lastFile)
            {
                if (run.IRTPeaks != null && run.IRTPeaks.Count() > 0)
                {
                    string[] iRTFilename = { "AllIRTMetrics_", date, ".tsv" };
                    fileMaker.CombineMultipleFilesIntoSingleFile(date + "_iRTMetrics_*", string.Join("", iRTFilename));
                }

                string[] swathFilename         = { "AllMetricsBySwath_", date, ".tsv" };
                string[] rtFilename            = { "AllRTDividedMetrics_", date, ".tsv" };
                string[] ComprehensiveFilename = { "AllComprehensiveMetrics_", date, ".tsv" };
                fileMaker.CheckOutputDirectory(inputFilePath);
                fileMaker.CombineMultipleFilesIntoSingleFile(date + "_MetricsBySwath_*", string.Join("", swathFilename));
                fileMaker.CombineMultipleFilesIntoSingleFile(date + "_RTDividedMetrics_*", string.Join("", rtFilename));
                fileMaker.CombineMultipleFilesIntoSingleFile(date + "_ComprehensiveMetrics_*", string.Join("", ComprehensiveFilename));
            }

            return(AssembleMetrics());
        }
Esempio n. 5
0
        public SwathMetrics GroupBySwath(MzmlParser.Run run)
        {
            //Create list of target isolationwindows to serve as swathnumber
            List <double> swathTargets = new List <double>();

            swathTargets = run.Ms2Scans.OrderBy(y => y.ScanStartTime).Select(x => x.IsolationWindowTargetMz).Distinct().ToList();
            double totalTIC = 0;

            foreach (var scan in run.Ms2Scans)
            {
                totalTIC += scan.TotalIonCurrent;
            }

            //Loop through every swath of a certain swathNumber:

            List <int>    numOfSwathPerGroup = new List <int>();
            List <double> TICs                      = new List <double>();
            List <double> swDensity                 = new List <double>();
            List <double> swDensity50               = new List <double>();
            List <double> swDensityIQR              = new List <double>();
            List <double> mzTargetRange             = new List <double>();
            List <double> averageMzTargetRange      = new List <double>();
            List <double> SwathProportionOfTotalTIC = new List <double>();
            List <double> TotalSwathProportionPredictedSingleCharge = new List <double>();
            List <double> SwathProportionPredictedSingleChargeAvg   = new List <double>();

//Loop through all the swaths of the same number and add to
            for (int swathNumber = 0; swathNumber < swathTargets.Count(); swathNumber++)
            {
                int track = 0;

                double TICthisSwath = 0;

                var orderedMS2Scans = run.Ms2Scans.OrderBy(s => s.ScanStartTime)
                                      .Where(x => x.MsLevel == 2 && x.IsolationWindowTargetMz == swathTargets[swathNumber]);
                foreach (var scan in orderedMS2Scans)
                {
                    mzTargetRange.Add(scan.IsolationWindowUpperOffset + scan.IsolationWindowLowerOffset);
                    TICthisSwath = TICthisSwath + scan.TotalIonCurrent;
                    swDensity.Add(scan.Density);
                    TotalSwathProportionPredictedSingleCharge.Add(scan.ProportionChargeStateOne); //The chargestate one's we pick up is where there is a match for M+1. Therefore we need to double it to add the M.
                    track++;
                }
                averageMzTargetRange.Add(mzTargetRange.Average());
                numOfSwathPerGroup.Add(track);
                TICs.Add(TICthisSwath);
                TICthisSwath = 0;
                SwathProportionPredictedSingleChargeAvg.Add(TotalSwathProportionPredictedSingleCharge.Average());
                TotalSwathProportionPredictedSingleCharge.Clear();
                swDensity.Sort();
                swDensity50.Add(Math.Truncate(Math.Ceiling(swDensity.Average())));
                swDensityIQR.Add(Math.Truncate(Math.Ceiling(InterQuartileRangeCalculator.CalcIQR(swDensity))));
                swDensity.Clear();
                mzTargetRange.Clear();
            }

            for (int num = 0; num < swathTargets.Count(); num++)
            {
                SwathProportionOfTotalTIC.Add(TICs[num] / totalTIC);
            }

            SwathMetrics swathMetrics = new SwathMetrics(swathTargets, totalTIC, numOfSwathPerGroup, averageMzTargetRange, TICs, swDensity50, swDensityIQR, SwathProportionOfTotalTIC, SwathProportionPredictedSingleChargeAvg);

            return(swathMetrics);
        }