private List <string> ExecuteChromosomeJobs(Dictionary <string, int> chromRefIds,
                                                    string outMultiPath, List <string> taskDirectories)
        {
            var orderedChroms = MultiProcessHelpers.GetOrderedChromosomes(chromRefIds).ToList();
            ConcurrentQueue <string> input = new ConcurrentQueue <string>(orderedChroms);

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            var tasks      = new List <Task>();
            var pathsArray = new string[chromRefIds.Max(x => x.Value) + 1];

            using (var concurrencySemaphore = new SemaphoreSlim(_options.NumProcesses))
            {
                foreach (var chrom in orderedChroms)
                {
                    {
                        var options = new GeminiMultiOptions()
                        {
                            StitcherOptions       = (_options.StitcherOptions.DeepCopy()),
                            GeminiSampleOptions   = (_options.GeminiSampleOptions.DeepCopy()),
                            IndelFilteringOptions =
                                (_options.IndelFilteringOptions.DeepCopy()),
                            RealignmentAssessmentOptions =
                                (_options.RealignmentAssessmentOptions.DeepCopy()),
                            RealignmentOptions = (_options.RealignmentOptions.DeepCopy()),

                            GeminiOptions   = (_options.GeminiOptions.DeepCopy()),
                            InputBam        = _options.InputBam,
                            OutputDirectory = _options.OutputDirectory
                        };


                        Console.WriteLine($"Waiting to launch job for chrom {chrom}");
                        Console.WriteLine($"Launching job for chrom {chrom}");
                        concurrencySemaphore.Wait();
                        tasks.Add(Task.Factory.StartNew(() =>
                        {
                            try
                            {
                                pathsArray[chromRefIds[chrom]] = ProcessChromosome(chromRefIds, outMultiPath, taskDirectories, chrom, options);
                            }
                            finally
                            {
                                concurrencySemaphore.Release();
                            }
                        }));
                    }
                }

                Logger.WriteToLog("Launched all tasks.");
                Task.WaitAll(tasks.ToArray());

                return(pathsArray.Where(x => x != null).ToList());
            }
        }
        private static string ProcessChromosome(Dictionary <string, int> chromRefIds, string outMultiPath, List <string> taskDirectories,
                                                string chrom, GeminiMultiOptions options)
        {
            // TODO either officially deprecate non-multiprocess-processing and remove this, or consolidate this with the Gemini calling code from Gemini/Program.cs

            var outdir       = Path.Combine(outMultiPath, chrom);
            var refId        = chromRefIds[chrom];
            var intermediate = string.IsNullOrEmpty(options.GeminiSampleOptions.IntermediateDir)
                ? null
                : Path.Combine(options.GeminiSampleOptions.IntermediateDir, chrom);
            var geminiSampleOptions = new GeminiSampleOptions
            {
                InputBam        = options.InputBam,
                OutputFolder    = outdir,
                OutputBam       = Path.Combine(outdir, "out.bam"),
                IntermediateDir = intermediate,
                RefId           = refId
            };

            // Gemini defaults different than stitcher defaults
            options.StitcherOptions.NifyUnstitchablePairs = false;

            // Set stitcher pair-filter-level duplicate filtering if skip and remove dups, to save time
            options.StitcherOptions.FilterDuplicates = options.GeminiOptions.SkipAndRemoveDups;

            var dataSourceFactory = new GeminiDataSourceFactory(options.StitcherOptions, options.GeminiOptions.GenomePath,
                                                                options.GeminiOptions.SkipAndRemoveDups, refId,
                                                                Path.Combine(outdir, "Regions.txt"), debug: options.GeminiOptions.Debug);
            var dataOutputFactory = new GeminiDataOutputFactory(options.StitcherOptions.NumThreads);
            var samtoolsWrapper   = new SamtoolsWrapper(options.GeminiOptions.SamtoolsPath, options.GeminiOptions.IsWeirdSamtools);

            var geminiWorkflow = new GeminiWorkflow(dataSourceFactory, dataOutputFactory,
                                                    options.GeminiOptions, geminiSampleOptions, options.RealignmentOptions, options.StitcherOptions, options.OutputDirectory, options.RealignmentAssessmentOptions, options.IndelFilteringOptions, samtoolsWrapper);

            Directory.CreateDirectory(outdir);
            geminiWorkflow.Execute();

            //var logger = new Illumina.CG.Common.Logging.Logger(taskLogDir, $"GeminiTaskLog_{chrom}.txt");
            //var task = _taskCreator.GetCliTask(cmdLineList.ToArray(), chrom, exePath, outdir, chromRefIds[chrom], logger,
            //    string.IsNullOrEmpty(_options.GeminiSampleOptions.IntermediateDir)
            //        ? null
            //        : Path.Combine(_options.GeminiSampleOptions.IntermediateDir, chrom));

            //tasks.Add(task);

            Console.WriteLine($"Completed Gemini Workflow for {chrom}");

            var path = (Path.Combine(outdir, "merged.bam.sorted.bam"));

            taskDirectories.Add(outdir);
            //paths[refId] = path;
            return(path);
        }