The molecule workflow parameters.
        /// <summary>
        /// The find optimum hypothesis.
        /// </summary>
        /// <param name="observations">
        /// The observations.
        /// </param>
        /// <param name="driftTubeLength">
        /// The drift Tube Length.
        /// </param>
        /// <param name="massTarget">
        /// The mass Target.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <returns>
        /// The <see cref="AssociationHypothesis"/>.
        /// </returns>
        /// <exception cref="NotImplementedException">
        /// </exception>
        public AssociationHypothesis FindOptimumHypothesis(IEnumerable<ObservedPeak> observations, double driftTubeLength, IImsTarget massTarget, CrossSectionSearchParameters parameters, int numberOfVoltageGroups)
        {
            observations = observations.ToList();

            ObservationTransitionGraph<IonTransition> transitionGraph = new ObservationTransitionGraph<IonTransition>(observations, (a, b) => new IonTransition(a, b));

            // Visualize the graph.
            // transitionGraph.PlotGraph();

            // Find all the possible combinotorial tracks
            // IList<IsomerTrack> candidateTracks = this.FindAllReasonableTracks(transitionGraph, driftTubeLength, massTarget, parameters).ToList();

            // Find the top N tracks using K shorestest path algorithm
            IEnumerable<IEnumerable<IonTransition>> kShorestPaths = transitionGraph.PeakGraph.RankedShortestPathHoffmanPavley(t => 0 - Math.Log(t.TransitionProbability), transitionGraph.SourceVertex, transitionGraph.SinkVertex, this.maxTracks);

            IEnumerable<IsomerTrack> candidateTracks = MinCostFlowIonTracker.ToTracks(kShorestPaths, parameters, numberOfVoltageGroups, parameters.RegressionSelection);

            // filter paths
            TrackFilter filter = new TrackFilter();
            Predicate<IsomerTrack> trackPredicate = track => filter.IsTrackPossible(track, massTarget, parameters);
            List<IsomerTrack> filteredTracks = candidateTracks.ToList().FindAll(trackPredicate);

            // Select the top N tracks to proceed to next step.
            var hypotheses = this.FindAllHypothesis(filteredTracks, observations).ToArray();

            // Find the combination of tracks that produces the highest posterior probablity.
              IOrderedEnumerable<AssociationHypothesis> sortedAssociationHypotheses = hypotheses.OrderByDescending(h => h.ProbabilityOfHypothesisGivenData);

            return sortedAssociationHypotheses.FirstOrDefault();
        }
 public AssociationHypothesis FindOptimumHypothesis(
     IEnumerable<ObservedPeak> observations,
     double driftTubeLength,
     IImsTarget target,
     CrossSectionSearchParameters parameters)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// The to tracks.
        /// </summary>
        /// <param name="edges">
        /// The edges.
        /// </param>
        /// <param name="parameters"></param>
        /// <returns>
        /// The <see cref="IEnumerable"/>.
        /// </returns>
        public static IEnumerable<IsomerTrack> ToTracks(IEnumerable<IEnumerable<IonTransition>> edges, CrossSectionSearchParameters parameters, int numberOfVoltageGroups, FitlineEnum fitlineType)
        {
            foreach (IEnumerable<IonTransition> rawTrack in edges)
            {
                FitLine newFitline = (fitlineType == FitlineEnum.OrdinaryLeastSquares) ? (FitLine)new LeastSquaresFitLine() : new IRLSFitline(10000);
                IsomerTrack track = ToTrack(rawTrack, parameters, numberOfVoltageGroups, newFitline);

                yield return track;
            }
        }
        public static IsomerTrack ToTrack(IEnumerable<IonTransition> edges, CrossSectionSearchParameters parameters, int totalNumberOfVoltageGroups, FitLine fitline)
        {
            IsomerTrack track = new IsomerTrack(parameters.DriftTubeLengthInCm, totalNumberOfVoltageGroups, fitline, parameters.UseAverageTemperature);
            foreach (IonTransition edge in edges)
            {
                track.AddIonTransition(edge);
                ObservedPeak target = edge.Target;
                if (target.ObservationType != ObservationType.Virtual)
                {
                    track.AddObservation(target);
                }
            }

            return track;
        }
        internal static CrossSectionWorkflowResult CreateResultFromAssociationHypothesis(CrossSectionSearchParameters parameters, AssociationHypothesis optimalHypothesis, IImsTarget target, IEnumerable<VoltageGroup> allVoltageGroups, IEnumerable<ObservedPeak> allPeaks, string datasetPath, string analysisPath, string  sampleCollectionDate, double viperCompatibleMass = 0)
        {
            // Initialize the result struct.
            AssociationHypothesisInfo associationHypothesisInfo = new AssociationHypothesisInfo(optimalHypothesis.ProbabilityOfDataGivenHypothesis, optimalHypothesis.ProbabilityOfHypothesisGivenData);

            double averageVoltageGroupScore = VoltageGroupScoring.ComputeAverageVoltageGroupStabilityScore(allVoltageGroups);
            IEnumerable<PeakScores> allFeatureStatistics = allPeaks.Select(x => x.Statistics);
            PeakScores averageObservedPeakStatistics = FeatureScoreUtilities.AverageFeatureStatistics(allFeatureStatistics);

            IEnumerable<IsomerTrack> tracks = optimalHypothesis.Tracks.ToList();

            // Find the conformer with the closest m/z
            IsomerTrack trackWithBestMz = tracks.OrderBy(x => Math.Abs(Metrics.DaltonToPpm(x.AverageMzInDalton - target.MassWithAdduct, target.MassWithAdduct))).First();
            double bestMzInPpm = Metrics.DaltonToPpm(trackWithBestMz.AverageMzInDalton - target.MassWithAdduct, target.MassWithAdduct);
            IList<IdentifiedIsomerInfo> isomersInfo = tracks.Select(x => x.ExportIdentifiedIsomerInfo(viperCompatibleMass, allVoltageGroups.Count() - parameters.MaxOutliers, parameters.MinR2,  target, bestMzInPpm)).ToList();

            AnalysisStatus finalStatus = TrackToHypothesisConclusionLogic(isomersInfo.Select(info => info.AnalysisStatus));

            CrossSectionWorkflowResult informedResult = new CrossSectionWorkflowResult(
            datasetPath,
            target,
            finalStatus,
            associationHypothesisInfo,
            isomersInfo,
            averageObservedPeakStatistics,
            averageVoltageGroupScore,
            analysisPath,
            sampleCollectionDate
            );

            return informedResult;
        }
        /// <summary>
        /// The input UIMF file needs to be a UIMF file created by direct-injection
        /// IMS, with different drift tube voltages at different frames.
        /// This constructor intelligently group voltages together by observing
        /// sharp changes in running voltage standard deviation. The entire mobility
        /// and frame range would be accumulated.
        /// </summary>
        /// <param name="startScan">
        /// The start scan.
        /// </param>
        /// <param name="endScan">
        /// The end scan.
        /// </param>
        /// <param name="startBin">
        /// The start bin.
        /// </param>
        /// <param name="endBin">
        /// The end bin.
        /// </param>
        /// <param name="xCompression">
        /// The x compression.
        /// </param>
        /// <param name="yCompression">
        /// The y compression.
        /// </param>
        /// <param name="fullScan">
        /// The full Scan.
        /// </param>
        /// <param name="exportFormat">
        /// The export Format.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        private bool RunVoltageAccumulationWorkflow(int startScan, int endScan, int startBin, int endBin, double xCompression, double yCompression, bool fullScan, FileFormatEnum exportFormat)
        {
            CrossSectionSearchParameters defaultParams = new CrossSectionSearchParameters(88);
            VoltageSeparatedAccumulatedXiCs accumulatedXiCs = new VoltageSeparatedAccumulatedXiCs(this.UimfReader, 100, defaultParams.MzWindowHalfWidthInPpm, defaultParams.DriftTubeLengthInCm);
            IEnumerable<VoltageGroup> voltageGroups = accumulatedXiCs.Keys;
            bool success = true;
            foreach (var voltageGroup in voltageGroups)
            {
                // convert to MzML or UIMFs
                if (exportFormat == FileFormatEnum.UIMF)
                {
                    string outputPath = Path.Combine(this.OutputDir, this.datasetName + "_" + Math.Round(voltageGroup.MeanVoltageInVolts) + "V.uimf");
                    UimfExporter uimfExporter = new UimfExporter();
                    success = success && uimfExporter.ExportVoltageGroupAsSingleFrameUimf(outputPath, voltageGroup, this.UimfReader, this.averageNotSum, startScan, endScan, startBin, endBin, xCompression, yCompression, fullScan);
                    Console.WriteLine("Writing UIMF files to {0}", outputPath);
                }
                else if (exportFormat == FileFormatEnum.MzML)
                {
                    string outputPath = Path.Combine(this.OutputDir, this.datasetName + "_" + Math.Round(voltageGroup.MeanVoltageInVolts) + "V.mzML");
                    RetentionMobilitySwappedMzMLExporter mzMLExporter = new RetentionMobilitySwappedMzMLExporter();
                    success = success && mzMLExporter.ExportMzML(this.inputPath, outputPath, voltageGroup, this.UimfReader, this.averageNotSum);
                    Console.WriteLine("Writing MzML files to {0}", outputPath);
                }
            }

            return success;
        }
        public void TestTargetDetectionWithIsomersHard()
        {
            // BHC
            string formula3 = "C13H18ClNO";
            MolecularTarget sample3 = new MolecularTarget(formula3, IonizationMethod.Protonated, "BHC");
            string fileLocation3 = BHC;

            CrossSectionSearchParameters parameters3 = new CrossSectionSearchParameters(testDriftTubeLength);

            CrossSectionWorkfow workfow3 = new CrossSectionWorkfow(fileLocation3, "output", parameters3);
            CrossSectionWorkflowResult results3 = workfow3.RunCrossSectionWorkFlow(sample3, true);
            Assert.AreEqual(2, results3.IdentifiedIsomers.Count());
            workfow3.Dispose();
        }
        public int TestTargetDetectionWithIsomersClean(string formula, IonizationMethod method, string descriptor, string fileLocation)
        {
            MolecularTarget sample1 = new MolecularTarget(formula, method, descriptor);

            CrossSectionSearchParameters parameters1 = new CrossSectionSearchParameters(CrossSectionSearchParameters.DefaultDriftTimeToleranceInMs, CrossSectionSearchParameters.DefaultMzWindowHalfWidthInPpm,
                CrossSectionSearchParameters.DefaultNumPointForSmoothing, CrossSectionSearchParameters.DefaultFeatureFilterLevel, CrossSectionSearchParameters.DefaultAbsoluteIntensityThreshold, CrossSectionSearchParameters.DefaultPeakShapeThreshold, CrossSectionSearchParameters.DefaultIsotopicThreshold, CrossSectionSearchParameters.DefaultMaxOutliers, CrossSectionSearchParameters.DefaultPeakDetectorSelection, FitlineEnum.OrdinaryLeastSquares, CrossSectionSearchParameters.DefaultMinR2, CrossSectionSearchParameters.DefaultRelativeIntensityPercentageThreshold, "png", CrossSectionSearchParameters.DefaultInsufficientFramesFraction, testDriftTubeLength, true);

            CrossSectionWorkfow workfow1 = new CrossSectionWorkfow(fileLocation, "output", parameters1);
            CrossSectionWorkflowResult results1 = workfow1.RunCrossSectionWorkFlow(sample1, true);
            int count = results1.IdentifiedIsomers.Count();
            workfow1.Dispose();
            return count;
        }
        public void TestSingleMoleculeWithFormula()
        {
            // Nicotine
            // string formula = "C10H14N2";
            // ImsTarget sample = new ImsTarget(1, Adduct.Protonated, formula);
            // Console.WriteLine("MZ:   " +  221.0594);
            // string fileLocation = AcetamipridFile;

            // Acetamiprid
            // string formula = "C10H11ClN4";
            // ImsTarget sample = new ImsTarget(1, Adduct.Deprotonated, formula);
            // string fileLocation = AcetamipridFile;

            // F1E
            // string formula = "C15H21Cl2FN2O3";
            // MolecularTarget sample = new MolecularTarget(formula, IonizationMethod.Protonated);
            // string fileLocation = F1E;

            // BPS Negative
            // string formula = "C12H10O4S";
            // MolecularTarget sample = new MolecularTarget(formula, IonizationMethod.prot);
            // string fileLocation = BPSNegative;

            // BPS Positive
            string formula = "C12H10O4S";
            MolecularTarget sample = new MolecularTarget(formula, IonizationMethod.Protonated, "BPS");
            string fileLocation = BPSPostive;

            CrossSectionSearchParameters parameters = new CrossSectionSearchParameters(testDriftTubeLength);

            CrossSectionWorkfow workfow = new CrossSectionWorkfow(fileLocation, "output", parameters);
            CrossSectionWorkflowResult result = workfow.RunCrossSectionWorkFlow(sample, true);
            Assert.AreEqual(1, result.IdentifiedIsomers.Count());
            Assert.LessOrEqual(Math.Abs(result.IdentifiedIsomers.First().CrossSectionalArea - 166.3012), 0.5);
            workfow.Dispose();
        }
        public void TestSingleMoleculeMzOnly()
        {
            // Good BPS data
            double mz = 251.037804609;
            string uimfFile = BPSPostive;

            // Acetaminophen
            // double mz = 150.0555008;
            // string uimfFile = Acetaminophen;

            // Nicotinefnic
            // double mz = 161.10787;
            // string uimfFile = NicoFile;

            // Nico M+H
            // double mz = 161.10787;
            // string uimfFile = NicoFile;

            MolecularTarget target = new MolecularTarget(mz, IonizationMethod.Protonated, "Nicotine");

            CrossSectionSearchParameters parameters = new CrossSectionSearchParameters(testDriftTubeLength);

            CrossSectionWorkfow workflow = new CrossSectionWorkfow(uimfFile, "output",  parameters);
            workflow.RunCrossSectionWorkFlow(target);
            workflow.Dispose();
        }
        public void TestScoring()
        {
            string formula = "C9H13ClN6";
             string fileLocation = Cae;
             MolecularTarget target = new MolecularTarget(formula, IonizationMethod.Protonated, "CAE");

             Console.WriteLine("CompositionWithoutAdduct: " + target.CompositionWithoutAdduct);
             Console.WriteLine("Monoisotopic ViperCompatibleMass: " + target.MonoisotopicMass);

             CrossSectionSearchParameters parameters = new CrossSectionSearchParameters(driftTubeLength);

             var smoother = new SavitzkyGolaySmoother(parameters.NumPointForSmoothing, 2);

             CrossSectionWorkfow workflow = new CrossSectionWorkfow(fileLocation, "output", parameters);

             Console.WriteLine("Ionization method: " + target.Adduct);
             Console.WriteLine("Targeting centerMz: " + target.MassWithAdduct);

             // Generate Theoretical Isotopic Profile
             List<Peak> theoreticalIsotopicProfilePeakList = null;
             if (target.CompositionWithAdduct != null)
             {
                 string empiricalFormula = target.CompositionWithAdduct.ToPlainString();
                 var theoreticalFeatureGenerator = new JoshTheorFeatureGenerator();
                 IsotopicProfile theoreticalIsotopicProfile = theoreticalFeatureGenerator.GenerateTheorProfile(empiricalFormula, 1);
                 theoreticalIsotopicProfilePeakList = theoreticalIsotopicProfile.Peaklist.Cast<Peak>().ToList();
             }

             // Generate VoltageSeparatedAccumulatedXICs
             var uimfReader = new DataReader(fileLocation);
             Console.WriteLine("Input file: {0}", fileLocation);
             VoltageSeparatedAccumulatedXiCs accumulatedXiCs = new VoltageSeparatedAccumulatedXiCs(uimfReader, target.MassWithAdduct, parameters.MzWindowHalfWidthInPpm, driftTubeLength);

             Console.WriteLine();

             // For each voltage, find 2D XIC features
             foreach (VoltageGroup voltageGroup in accumulatedXiCs.Keys)
             {
                 Console.WriteLine("Voltage group: {0} V, Frame {1}-{2}, {3:F2}K, {4:F2}Torr",
                     voltageGroup.MeanVoltageInVolts,
                     voltageGroup.FirstFrameNumber,
                     voltageGroup.LastFrameNumber,
                     voltageGroup.MeanTemperatureInKelvin,
                     voltageGroup.MeanPressureInTorr);

                 List<IntensityPoint> intensityPoints = accumulatedXiCs[voltageGroup].IntensityPoints;
                 List<FeatureBlob> featureBlobs = PeakFinding.FindPeakUsingWatershed(intensityPoints, smoother, parameters.FeatureFilterLevel);
                 List<StandardImsPeak> standardPeaks = featureBlobs.Select(featureBlob => new StandardImsPeak(featureBlob, uimfReader, voltageGroup,  target.MassWithAdduct, parameters.MzWindowHalfWidthInPpm)).ToList();

                 // feature scorings and Target selection.
                 double globalMaxIntensity = IMSUtil.MaxIntensityAfterFrameAccumulation(voltageGroup, uimfReader);

                 // Check each XIC Peak found
                 foreach (var featurePeak in standardPeaks)
                 {
                     // Evaluate feature scores.
                    double intensityScore = FeatureScoreUtilities.IntensityScore(featurePeak, globalMaxIntensity);

                    double isotopicScoreAngle = FeatureScoreUtilities.IsotopicProfileScore(
                         featurePeak,
                         workflow.uimfReader,
                         target,
                         theoreticalIsotopicProfilePeakList,
                         voltageGroup,
                         IsotopicScoreMethod.Angle,
                         globalMaxIntensity,
                         workflow.NumberOfScans);

                     double isotopicScoreDistance = FeatureScoreUtilities.IsotopicProfileScore(
                         featurePeak,
                         workflow.uimfReader,
                         target,
                         theoreticalIsotopicProfilePeakList,
                         voltageGroup,
                         IsotopicScoreMethod.EuclideanDistance,
                         globalMaxIntensity,
                         workflow.NumberOfScans);

                     double isotopicScorePerson = FeatureScoreUtilities.IsotopicProfileScore(
                         featurePeak,
                         workflow.uimfReader,
                         target,
                         theoreticalIsotopicProfilePeakList,
                         voltageGroup,
                         IsotopicScoreMethod.PearsonCorrelation,
                         globalMaxIntensity,
                         workflow.NumberOfScans);

                     double isotopicScoreBhattacharyya = FeatureScoreUtilities.IsotopicProfileScore(
                         featurePeak,
                         workflow.uimfReader,
                         target,
                         theoreticalIsotopicProfilePeakList,
                         voltageGroup,
                         IsotopicScoreMethod.Bhattacharyya,
                         globalMaxIntensity,
                         workflow.NumberOfScans);

                     double isotopicScoreDistanceAlternative = FeatureScoreUtilities.IsotopicProfileScore(
                         featurePeak,
                         workflow.uimfReader,
                         target,
                         theoreticalIsotopicProfilePeakList,
                         voltageGroup,
                         IsotopicScoreMethod.EuclideanDistanceAlternative,
                         globalMaxIntensity,
                         workflow.NumberOfScans);

                     double peakShapeScore = FeatureScoreUtilities.PeakShapeScore(featurePeak, workflow.uimfReader, workflow.Parameters.MzWindowHalfWidthInPpm, workflow.Parameters.DriftTimeToleranceInMs, voltageGroup, globalMaxIntensity, workflow.NumberOfScans);

                     // Report all features.
                     Console.WriteLine(" feature found at scan number {0}", featurePeak.PeakApex.DriftTimeCenterInScanNumber);
                     Console.WriteLine("     IntensityScore: {0}", intensityScore);
                     Console.WriteLine("     peakShapeScore: {0}", peakShapeScore);
                     Console.WriteLine("     isotopicScore - Angle:    {0}", isotopicScoreAngle);
                     Console.WriteLine("     isotopicScore - Distance: {0}", isotopicScoreDistance);
                     Console.WriteLine("     isotopicScore - Distance2:{0}", isotopicScoreDistanceAlternative);
                     Console.WriteLine("     isotopicScore - Pearson:  {0}", isotopicScorePerson);
                     Console.WriteLine("     isotopicScore - Bhattacharyya: {0}", isotopicScoreBhattacharyya);

                     Console.WriteLine();
                 }

                 Console.WriteLine();
             }

             workflow.Dispose();
        }
        public void TestFileNotFound()
        {
            // Good BPS data
            double mz = 273.0192006876;
            string uimfFile = "blablabla";

            // Acetaminophen
            // double mz = 150.0555008;
            // string uimfFile = Acetaminophen;

            // Nicotinefnic
            // double mz = 161.10787;
            // string uimfFile = NicoFile;

            // AcetamipridFile
            // double mz = 221.059395;
            // string uimfFile = AcetamipridFile;

            MolecularTarget target = new MolecularTarget(mz, IonizationMethod.Deprotonated, "BPS");

            CrossSectionSearchParameters parameters = new CrossSectionSearchParameters(testDriftTubeLength);

            Assert.Throws<FileNotFoundException>(() => new CrossSectionWorkfow(uimfFile, "output", parameters));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="CrossSectionWorkfow"/> class.
        /// </summary>
        /// <param name="uimfFileLocation">
        /// The uimf file location.
        /// </param>
        /// <param name="outputDirectory">
        /// The output directory.
        /// </param>
        /// <param name="logFileName">
        /// The log file name.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        public CrossSectionWorkfow(string uimfFileLocation, string outputDirectory, CrossSectionSearchParameters parameters)
        {
            this.uimfReader = new DataReader(uimfFileLocation);

            // Append bin-centric table to the uimf if not present.
            if (!this.uimfReader.DoesContainBinCentricData())
            {
                DataWriter dataWriter = new DataWriter(uimfFileLocation);
                dataWriter.CreateBinCentricTables();
            }

            this.Parameters = parameters;

            this.smoother = new SavitzkyGolaySmoother(parameters.NumPointForSmoothing, 5);

            this.theoreticalFeatureGenerator = new JoshTheorFeatureGenerator();
            this.peakDetector = new ChromPeakDetector(0.0001, 0.0001);

            this.NumberOfFrames = this.uimfReader.GetGlobalParams().NumFrames;
            this.NumberOfScans = this.uimfReader.GetFrameParams(1).Scans;
            this.SampleCollectionDate = this.uimfReader.GetGlobalParams().GetValue(GlobalParamKeyType.DateStarted);

            this.DatasetName = Path.GetFileNameWithoutExtension(uimfFileLocation);
            this.OutputPath = outputDirectory;
            this.DatasetPath = uimfFileLocation;

            this.Parameters = parameters;

            if (outputDirectory == string.Empty)
            {
                outputDirectory = Directory.GetCurrentDirectory();
            }

            if (!outputDirectory.EndsWith("\\"))
            {
                outputDirectory += "\\";
            }

            if (!Directory.Exists(outputDirectory))
            {
                try
                {
                    Directory.CreateDirectory(outputDirectory);
                }
                catch (Exception)
                {
                    Console.WriteLine("Failed to create directory.");
                    throw;
                }
            }

            this.OutputPath = outputDirectory;
        }
예제 #14
0
        /// <summary>
        /// The execute finder.
        /// </summary>
        /// <param name="options">
        /// The options.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        private static int ExecuteFinder(FinderOptions options)
        {
            try
            {
                string uimfFile = options.InputPath; // get the UIMF file
                string datasetName = Path.GetFileNameWithoutExtension(uimfFile);
                string resultName = datasetName + "_"  + "Result.bin";
                string resultPath = Path.Combine(options.OutputPath, resultName);
                string outputDirectory = options.OutputPath;
                IList<string> targetList = options.TargetList;
                bool verbose = options.DetailedVerbose;

                if (outputDirectory == string.Empty)
                {
                    outputDirectory = Directory.GetCurrentDirectory();
                } 
                
                if (!outputDirectory.EndsWith("\\"))
                {
                    outputDirectory += "\\";
                }

                if (!Directory.Exists(outputDirectory))
                {
                    try
                    {
                        Directory.CreateDirectory(outputDirectory);
                    }
                    catch (Exception)
                    {
                        Console.WriteLine("Failed to create directory.");
                        throw;
                    }
                }

                // Delete the result file if it already exists
                if (File.Exists(resultPath))
                {
                    File.Delete(resultPath);
                }

                // Load parameters
                double Mz;

                CrossSectionSearchParameters searchParameters = new CrossSectionSearchParameters(
                    options.DriftTimeToleranceInMs,
                    options.PrePpm,
                    options.NumberOfPointsForSmoothing,
                    options.FeatureFilterLevel,
                    options.IntensityThreshold,
                    options.PeakShapeScoreThreshold,
                    options.IsotopicScoreThreshold,
                    options.MaxOutliers,
                    CrossSectionSearchParameters.DefaultPeakDetectorSelection, // No longer an option
                    options.RobustRegression ? FitlineEnum.IterativelyBiSquareReweightedLeastSquares : FitlineEnum.OrdinaryLeastSquares,
                    options.MinR2,
                    options.RelativeIntensityPercentageThreshold,
                    options.GraphicsFormat,
                    options.InsufficientFramesFraction,
                    options.DriftTubeLength,
                    options.UseAverageTemperature);

                IFormatter formatter = new BinaryFormatter();

                // If target cannot be constructed. Create a result.
                IList<IImsTarget> targets = new List<IImsTarget>(); 
                IImsTarget currentTarget = null;
                IList<CrossSectionWorkflowResult> errorTargets = new List<CrossSectionWorkflowResult>();
                foreach (string item in targetList)
                {
                    foreach (string ionization in options.IonizationList)
                    {
                        try
                        {
                            // get the ionization method.
                            IonizationMethod method = IonizationMethodUtilities.ParseIonizationMethod(ionization.Trim());

                            Tuple<string, string> target = ParseTargetToken(item, datasetName);
                            string formula = target.Item2;
                            string sampleClass = target.Item1;

                            bool isDouble = Double.TryParse(formula, out Mz);
                            if (!isDouble)
                            {
                                Regex rgx = new Regex("[^a-zA-Z0-9 -]");
                                formula = rgx.Replace(formula, "");
                            }

                            if (!isDouble)
                            {
                                currentTarget = new MolecularTarget(formula, method, sampleClass);
                                targets.Add(currentTarget);
                            }

                            else 
                            {
                                currentTarget = new MolecularTarget(Mz, method, sampleClass);
                                targets.Add(currentTarget);
                            }
                        }
                        catch (Exception e)
                        {
                            // In case of error creating targets, create the target error result
                            CrossSectionWorkflowResult informedResult = CrossSectionWorkflowResult.CreateErrorResult(currentTarget, datasetName, uimfFile, resultPath, "");
                            
                            using (Stream stream = new FileStream("serialized_result.bin", FileMode.Create, FileAccess.Write, FileShare.None))
                            {
                                formatter.Serialize(stream, informedResult);
                            }

                            throw e;
                        }
                    }
                } 
                        
                // Preprocessing
                Console.WriteLine("Start Preprocessing:");
                BincCentricIndexing.IndexUimfFile(uimfFile);

                // Run algorithms in IMSInformed
                CrossSectionWorkfow workflow = new CrossSectionWorkfow(uimfFile, outputDirectory, searchParameters);
                IList<CrossSectionWorkflowResult> results = workflow.RunCrossSectionWorkFlow(targets, verbose);
                workflow.Dispose();

                // Merge the target error result dictionary and other results
                foreach (var pair in errorTargets)
                {
                    results.Add(pair);
                }

                // Serialize the result
                string binPath = Path.Combine(outputDirectory, resultName);

                using (Stream stream = new FileStream(binPath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                        formatter.Serialize(stream, results);
                }
                
                if (options.PauseWhenDone)
                {
                    PauseProgram();
                }

                // Define success
                foreach (CrossSectionWorkflowResult result in results)
                {
                    if (!(result.AnalysisStatus == AnalysisStatus.Positive || result.AnalysisStatus == AnalysisStatus.Negative || result.AnalysisStatus == AnalysisStatus.NotSufficientPoints | result.AnalysisStatus == AnalysisStatus.Rejected))
                    {
                        return 1;
                    }
                }

                return 0;
            }
            catch (Exception e)
            {
                string uimfFile = options.InputPath; // get the UIMF file
                string datasetName = Path.GetFileNameWithoutExtension(uimfFile);
                string resultName = datasetName + "_Result.txt";
                string resultPath = Path.Combine(options.OutputPath, resultName);
                string outputDirectory = options.OutputPath;

                if (outputDirectory == string.Empty)
                {
                    outputDirectory = Directory.GetCurrentDirectory();
                } 
                
                if (!outputDirectory.EndsWith("\\"))
                {
                    outputDirectory += "\\";
                }

                if (!Directory.Exists(outputDirectory))
                {
                    try
                    {
                        Directory.CreateDirectory(outputDirectory);
                    }
                    catch (Exception)
                    {
                        Console.WriteLine("Failed to create directory.");
                        throw;
                    }
                }

                // Delete the result file if it already exists
                if (File.Exists(resultPath))
                {
                    File.Delete(resultPath);
                }

                Console.WriteLine(e.Message);
                using (StreamWriter errorFile = File.CreateText(resultPath))
                {
                    errorFile.Write(e.Message);
                    errorFile.Write(e.StackTrace);
                }

                if (options.PauseWhenDone)
                {
                    PauseProgram();
                }

                return 1;
            }
        }
        public void TestMixedSampleCrossSectionExtraction()
        {
            string fileLocation = @"\\proto-2\UnitTest_Files\IMSInformedTestFiles\datasets\mix\Mix1_8Oct13_Columbia_DI.uimf";
            IonizationMethod method = IonizationMethod.Sodiumated;

            IList<IImsTarget> targetList = new List<IImsTarget>();
            targetList.Add(new PeptideTarget(12, "DGWHSWPIAHQWPQGPSAVDAAFSWEEK", 1.0));
            targetList.Add(new MolecularTarget("C3H7O7P", method, "chemical A"));
            targetList.Add(new MolecularTarget("C3H7O7P", method, "chemical B(A's isomer)"));
            targetList.Add(new MolecularTarget("C6H14O12P2", method, "chemical C"));
            targetList.Add(new MolecularTarget("C4H6O5", method, "chemical D"));
            targetList.Add(new MolecularTarget("C3H4O3", method, "chemical E"));
            targetList.Add(new MolecularTarget("C5H11O8P", method, "chemical F"));
            targetList.Add(new MolecularTarget("C6H8O7", method, "chemical G"));
            targetList.Add(new MolecularTarget("C4H6O4", method, "chemical H"));
            targetList.Add(new MolecularTarget("C3H5O6P", method, "chemical I"));
            targetList.Add(new MolecularTarget("C7H15O10P", method, "chemical J"));
            targetList.Add(new MolecularTarget(120.5, method, "MzInDalton specified chemical L"));

            Console.WriteLine("TargetList: ");

            CrossSectionSearchParameters parameters = new CrossSectionSearchParameters(testDriftTubeLength);

            CrossSectionWorkfow informedWorkflow = new CrossSectionWorkfow(fileLocation, "output", parameters);
            IEnumerable<CrossSectionWorkflowResult> resultMap = informedWorkflow.RunCrossSectionWorkFlow(targetList, false);
            informedWorkflow.Dispose();
        }
        /// <summary>
        /// The is track possible.
        /// </summary>
        /// <param name="track">
        /// The track.
        /// </param>
        /// <param name="target"></param>
        /// <param name="crossSectionSearchParameters"></param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public bool IsTrackPossible(IsomerTrack track, IImsTarget target, CrossSectionSearchParameters crossSectionSearchParameters)
        {
            int minFitPoints = track.TotalNumberOfVoltageGroups - crossSectionSearchParameters.MaxOutliers;
            if (this.FilterLowFitPointNumber(track.RealPeakCount, minFitPoints))
            {
                return false;
            }

            MobilityInfo trackMobilityInfo = track.GetMobilityInfoForTarget(target);
            if (!this.IsConsistentWithIonDynamics(trackMobilityInfo))
            {
                return false;
            }

            if (this.IsLowR2(trackMobilityInfo.RSquared, crossSectionSearchParameters.MinR2))
            {
                return false;
            }

            return true;
        }
        public void TestFormulaPerturbance()
        {
            List<Tuple<string, string>> formulas = new List<Tuple<string, string>>();

             // truth
             formulas.Add(new Tuple<string, string>("True formula", "C12H10O4S"));
             formulas.Add(new Tuple<string, string>("1 extra H", "C12H11O4S"));
             formulas.Add(new Tuple<string, string>("2 extra H", "C12H12O4S"));
             formulas.Add(new Tuple<string, string>("3 extra H", "C12H13O4S"));
             formulas.Add(new Tuple<string, string>("3 extra H", "C12H14O4S"));
             formulas.Add(new Tuple<string, string>("4 extra H", "C12H15O4S"));
             formulas.Add(new Tuple<string, string>("5 extra H", "C12H16O4S"));
             formulas.Add(new Tuple<string, string>("1 less H", "C12H9O4S"));
             formulas.Add(new Tuple<string, string>("2 less H", "C12H8O4S"));
             formulas.Add(new Tuple<string, string>("3 less H", "C12H7O4S"));
             formulas.Add(new Tuple<string, string>("4 less H", "C12H6O4S"));
             Console.WriteLine("[Intensity], [Distance1], [Distance2], [Angle], [Pearson], [Bucha]");

             string fileLocation = BPSNegative;
             CrossSectionSearchParameters parameters = new CrossSectionSearchParameters(driftTubeLength);
             CrossSectionWorkfow workflow = new CrossSectionWorkfow(fileLocation, "output", parameters);

             foreach (var form in formulas)
             {
                 bool found = false;

                 MolecularTarget target = new MolecularTarget(form.Item2, new IonizationAdduct(IonizationMethod.Deprotonated), form.Item1);
                 Console.Write(form.Item1 + ": ");
                 var smoother = new SavitzkyGolaySmoother(parameters.NumPointForSmoothing, 2);

                 // Generate Theoretical Isotopic Profile
                 List<Peak> theoreticalIsotopicProfilePeakList = null;
                 if (target.CompositionWithAdduct != null)
                 {
                     string empiricalFormula = target.CompositionWithAdduct.ToPlainString();
                     var theoreticalFeatureGenerator = new JoshTheorFeatureGenerator();
                     IsotopicProfile theoreticalIsotopicProfile = theoreticalFeatureGenerator.GenerateTheorProfile(empiricalFormula, 1);
                     theoreticalIsotopicProfilePeakList = theoreticalIsotopicProfile.Peaklist.Cast<Peak>().ToList();
                 }

                 // Generate VoltageSeparatedAccumulatedXICs
                 var uimfReader = new DataReader(fileLocation);
                 VoltageSeparatedAccumulatedXiCs accumulatedXiCs = new VoltageSeparatedAccumulatedXiCs(uimfReader, target.MassWithAdduct, parameters.MzWindowHalfWidthInPpm, parameters.DriftTubeLengthInCm);

                 var voltageGroup = accumulatedXiCs.Keys.First();

                 // Find peaks using multidimensional peak finder.
                 List<IntensityPoint> intensityPoints = accumulatedXiCs[voltageGroup].IntensityPoints;
                 List<FeatureBlob> featureBlobs = PeakFinding.FindPeakUsingWatershed(intensityPoints, smoother, parameters.FeatureFilterLevel);
                 List<StandardImsPeak> standardPeaks = featureBlobs.Select(featureBlob => new StandardImsPeak(featureBlob, uimfReader, voltageGroup,  target.MassWithAdduct, parameters.MzWindowHalfWidthInPpm)).ToList();

                 // feature scorings and Target selection.
                 double globalMaxIntensity = IMSUtil.MaxIntensityAfterFrameAccumulation(voltageGroup, uimfReader);

                 // Check each XIC Peak found
                 foreach (var peak in standardPeaks)
                 {
                     // Evaluate feature scores.
                     double intensityScore = FeatureScoreUtilities.IntensityScore(peak, globalMaxIntensity);

                     double isotopicScoreAngle = FeatureScoreUtilities.IsotopicProfileScore(
                         peak,
                         workflow.uimfReader,
                         target,
                         theoreticalIsotopicProfilePeakList,
                         voltageGroup,
                         IsotopicScoreMethod.Angle,
                         globalMaxIntensity,
                         workflow.NumberOfScans);

                     double isotopicScoreDistance = FeatureScoreUtilities.IsotopicProfileScore(
                         peak,
                         workflow.uimfReader,
                         target,
                         theoreticalIsotopicProfilePeakList,
                         voltageGroup,
                         IsotopicScoreMethod.EuclideanDistance,
                         globalMaxIntensity,
                         workflow.NumberOfScans);

                     double isotopicScorePerson = FeatureScoreUtilities.IsotopicProfileScore(
                         peak,
                         workflow.uimfReader,
                         target,
                         theoreticalIsotopicProfilePeakList,
                         voltageGroup,
                         IsotopicScoreMethod.PearsonCorrelation,
                         globalMaxIntensity,
                         workflow.NumberOfScans);

                     double isotopicScoreBhattacharyya = FeatureScoreUtilities.IsotopicProfileScore(
                         peak,
                         workflow.uimfReader,
                         target,
                         theoreticalIsotopicProfilePeakList,
                         voltageGroup,
                         IsotopicScoreMethod.Bhattacharyya,
                         globalMaxIntensity,
                         workflow.NumberOfScans);

                     double isotopicScoreDistanceAlternative = FeatureScoreUtilities.IsotopicProfileScore(
                         peak,
                         workflow.uimfReader,
                         target,
                         theoreticalIsotopicProfilePeakList,
                         voltageGroup,
                         IsotopicScoreMethod.EuclideanDistanceAlternative,
                         globalMaxIntensity,
                         workflow.NumberOfScans);

                     double peakShapeScore = FeatureScoreUtilities.PeakShapeScore(peak, workflow.uimfReader, workflow.Parameters.MzWindowHalfWidthInPpm, workflow.Parameters.DriftTimeToleranceInMs, voltageGroup, globalMaxIntensity, workflow.NumberOfScans);

                     // Report all features.
                     if (peak.PeakApex.DriftTimeCenterInScanNumber == 115)
                     {
                         Console.Write("{0:F4} ", intensityScore);
                         found = true;
                     }

                     // Report all features.
                     if (peak.PeakApex.DriftTimeCenterInScanNumber == 115)
                     {
                         Console.Write("{0:F4} ", isotopicScoreDistance);
                         found = true;
                     }

                     // Report all features.
                     if (peak.PeakApex.DriftTimeCenterInScanNumber == 115)
                     {
                         Console.Write("{0:F4} ", isotopicScoreDistanceAlternative);
                         found = true;
                     }

                     // Report all features.
                     if (peak.PeakApex.DriftTimeCenterInScanNumber == 115)
                     {
                         Console.Write("{0:F4} ", isotopicScoreAngle);
                         found = true;
                     }

                     // Report all features.
                     if (peak.PeakApex.DriftTimeCenterInScanNumber == 115)
                     {
                         Console.Write("{0:F4} ", isotopicScorePerson);
                         found = true;
                     }

                     // Report all features.
                     if (peak.PeakApex.DriftTimeCenterInScanNumber == 115)
                     {
                         Console.Write("{0:F4} ", isotopicScoreBhattacharyya);
                         found = true;
                     }
                 }

                 if (!found)
                 {
                     Console.Write("No features");
                 }

                 Console.WriteLine();
             }

             // Manually dispose so it doesn't interfere with other tests.
             workflow.Dispose();
        }