示例#1
0
        static double MZError = 10; //ppm

        static int Main(string[] args)
        {
            //Параметры соответствуют вводу в форму RawtoMGF
            //args[0] - имя Raw-файла
            //args[1] - имя MGF-файла
            //args[2] - minimal MZ
            //args[3] - maximal MZ
            //args[4] - minimal RT
            //args[5] - maximal RT
            //args[6] - minimal Charge
            //args[7] - maximal Charge
            //args[8] - number of top peaks
            //args[9] - CleanETD:yes / CleanETD:no
            //args[10] - Instrument:yes / Instrument:no
            //дополнительно (к версии 2.0.6)
            //args[11] - CheckSpectra:yes / CheckSpectra:no
            try{
                Console.ReadLine();
                //Thread.Sleep(30000);
                string InFileName      = args[0];
                string OutFileName     = args[1];
                double MinMZ           = Convert.ToDouble(args[2]);
                double MaxMZ           = Convert.ToDouble(args[3]);
                double MinRT           = Convert.ToDouble(args[4]);
                double MaxRT           = Convert.ToDouble(args[5]);
                int    MinCharge       = Convert.ToInt32(args[6]);
                int    MaxCharge       = Convert.ToInt32(args[7]);
                int    MaxPeakNumber   = Convert.ToInt32(args[8]);
                bool   CleanETD        = args[9].Contains("CleanETD:yes");
                bool   MarkInstrtument = args[10].Contains("Instrument:yes");
                bool   CheckSpectra    = args[11].Contains("CheckSpectra:yes");
                bool   RTApex          = args[12].Contains("RTApex:yes");

                string[] Refs = { "@cid", "@hcd", "@etd", "@ecd", "FTMS", "ITMS" };

                MSFileReader_XRawfile RawFile;
                int              Spectra, LocalCount = 0;
                string           Filter;
                MGFFile          MGF;
                MGFSpectrum      ms;
                Childs           ch;
                ChildbyIntensity ci = new ChildbyIntensity();
                ChildbyMass      cm = new ChildbyMass();


                int    ArraySize = 0;
                Object MassList, EmptyRef;
                Object Labels, Values;
                double temp      = 0.0;
                int    Progress  = 0;
                int    MSCount   = 0;
                int    MSMSCount = 0;

                if (RTApex)
                {
                    MSFileBox = new RawFileBox();
                    MSFileBox.LoadIndex(InFileName);
                    RawFileBox.RepProgress = RepProgress;
                    RawFile = MSFileBox.RawFile;
                }
                else
                {
                    RawFile = new MSFileReader_XRawfile();
                    RawFile.Open(InFileName);
                    RawFile.SetCurrentController(0, 1);
                }
                Spectra = 0;
                RawFile.GetNumSpectra(ref Spectra);
                if (Spectra == 0)
                {
                    throw new Exception("Cannot get spectra from the file " + InFileName + ", File is invalid, broken or empty");
                }
                MGF = new MGFFile();
                for (int j = 1; j <= Spectra; j++)
                {
                    Filter = null;
                    RawFile.GetFilterForScanNum(j, ref Filter);
                    if (Filter.IndexOf("ms2") == -1)
                    {
                        MSCount++;
                        if (!CheckSpectra)
                        {
                            continue;
                        }
                        else
                        {
                            ArraySize = 0;
                            MassList  = null;
                            EmptyRef  = null;
                            temp      = 0.0;
                            try {
                                RawFile.GetMassListFromScanNum(ref j, null, 0, 0, 0, 0,
                                                               ref temp, ref MassList, ref EmptyRef, ref ArraySize);
                                continue;
                            }catch {
                                Exception e = new Exception(string.Format("Scan #{0} cannot be loaded, probably RAW file is corrupted!", j));
                                throw e;
                            }
                        }
                    }
                    MSMSCount++;
                    ms = new MGFSpectrum();
                    //определяем родительскую массу, заряд и RT
                    Labels    = null;
                    Values    = null;
                    ArraySize = 0;
                    LocalCount++;
                    RawFile.GetTrailerExtraForScanNum(j, ref Labels, ref Values, ref ArraySize);
                    for (int k = 0; k < ArraySize; k++)
                    {
                        if ((Labels as Array).GetValue(k).ToString().Contains("Mono"))
                        {
                            ms.mz = Convert.ToDouble((Values as Array).GetValue(k).ToString());
                        }
                        if ((Labels as Array).GetValue(k).ToString().Contains("Charge State"))
                        {
                            ms.Charge = Convert.ToInt32((Values as Array).GetValue(k).ToString());
                        }
                    }
                    //Если не нашли в labels - берем из фильтра
                    if (ms.mz == 0.0)
                    {
                        string part = Filter.Substring(0, Filter.IndexOf('@'));
                        ms.mz = Convert.ToDouble(part.Substring(part.LastIndexOf(' ')));
                    }
                    Labels    = null;
                    Values    = null;
                    ArraySize = 0;
                    double RT = 0;
                    RawFile.GetStatusLogForScanNum(j, ref RT, ref Labels, ref Values, ref ArraySize);

                    RawFile.RTFromScanNum(j, ref ms.RT);
                    ms.ScanNumber = j;
                    //Фильтры
                    if (ms.Charge < MinCharge)
                    {
                        continue;
                    }
                    if (ms.Charge > MaxCharge)
                    {
                        continue;
                    }
                    if (ms.RT < MinRT)
                    {
                        continue;
                    }
                    if (MaxRT != 0.0 && ms.RT > MaxRT)
                    {
                        continue;
                    }
                    if (ms.mz < MinMZ)
                    {
                        continue;
                    }
                    if (MaxMZ != 0.0 && ms.mz > MaxMZ)
                    {
                        continue;
                    }
                    //забираем сам спектр
                    MassList  = null;
                    EmptyRef  = null;
                    ArraySize = 0;
                    temp      = 0.0;
                    try{
                        if (Filter.IndexOf("FTMS") != -1)
                        {
                            //извлекаем FTMS данные
                            (RawFile as IXRawfile2).GetLabelData(ref MassList, ref EmptyRef, ref j);
                            ArraySize = (MassList as Array).GetLength(1);
                            for (int k = 0; k < ArraySize; k++)
                            {
                                ch           = new Childs();
                                ch.Mass      = (double)(MassList as Array).GetValue(0, k);
                                ch.Intensity = (double)(MassList as Array).GetValue(1, k);
                                ms.Data.Add(ch);
                            }
                        }
                        else
                        {
                            //извлекаем ITMS данные
                            RawFile.GetMassListFromScanNum(ref j, null, 0, 0, 0, 1, ref temp, ref MassList, ref EmptyRef, ref ArraySize);
                            ArraySize = (MassList as Array).GetLength(1);
                            for (int k = 0; k < ArraySize; k++)
                            {
                                ch           = new Childs();
                                ch.Mass      = (double)(MassList as Array).GetValue(0, k);
                                ch.Intensity = (double)(MassList as Array).GetValue(1, k);
                                ms.Data.Add(ch);
                            }
                        }
                    }catch {
                        Exception e = new Exception(string.Format("Scan #{0} cannot be loaded, probably RAW file is corrupted!", j));
                        throw e;
                    }
                    if (RTApex)
                    {
                        ms.RTApex = CheckRTApex(ms.RT, ms.mz);
                    }

                    if (MarkInstrtument)
                    {
                        if (Filter.Contains("ecd") || Filter.Contains("etd"))
                        {
                            ms.Instrument = "ETD-TRAP";
                        }
                        else
                        {
                            ms.Instrument = "ESI-FTICR";
                        }
                    }
                    //очистить ETD если был такой запрос
                    if (CleanETD)
                    {
                        if (Filter.Contains("ecd") || Filter.Contains("etd"))
                        {
                            FilterETD(ref ms, Filter.Contains("FTMS"));
                        }
                    }
                    //сбросить лишние сигналы
                    if (MaxPeakNumber > 0 && ms.Data.Count > MaxPeakNumber)
                    {
                        ms.Data.Sort(ci);
                        ms.Data.RemoveRange(0, ms.Data.Count - MaxPeakNumber);
                        ms.Data.Sort(cm);
                    }
                    //сформировать TITLE
                    if (RTApex)
                    {
                        ms.Title = String.Format("Elution from: {0:f4} to {0:f4} RT Apex: {1:f2} FinneganScanNumber: {2}",
                                                 ms.RT, ms.RTApex, ms.ScanNumber);
                    }
                    else
                    {
                        ms.Title = String.Format("Elution from: {0:f4} to {0:f4} FinneganScanNumber: {1}",
                                                 ms.RT, ms.ScanNumber);
                    }
                    MGF.Spectra.Add(ms);
                    // рапортовать прогресс
                    GC.Collect(2);

                    if ((int)(((double)j / (double)Spectra) * 100.0) > Progress)
                    {
                        Progress = (int)(((double)j / (double)Spectra) * 100.0);
                        Console.WriteLine("{0}%... {1} {2}", Progress, MSCount, MSMSCount);
                    }

                    //backgroundWorker1.ReportProgress((int)(((double)LocalCount/(double)SpCount)*100.0));
                }
                MGF.MGFComments.Add(String.Format("Created by RawToMGF 2.1.3; Spectra obtained from {0}", InFileName));
                MGF.MGFComments.Add(String.Format("Filters: Parent m/z from {0} Th to {1} Th;", MinMZ, MaxMZ));
                MGF.MGFComments.Add(String.Format("         RT from {0} min. to {1} min.;", MinRT, MaxRT));
                MGF.MGFComments.Add(String.Format("         Charge state of parent ions minimum {0}, maximum {1};", MinCharge, MaxCharge));
                MGF.MGFComments.Add(String.Format("         Max number of peaks in MS/MS spectra - {0}", MaxPeakNumber));
                if (CleanETD)
                {
                    MGF.MGFComments.Add("         ETD spectra cleaned from precursors and neutral losses");
                }
                MGF.MGFWrite(OutFileName, true);
            }catch (Exception e) {
                Console.Write("Error:");
                Console.Write(e.Message);
                Console.WriteLine("STACKINFO:" + e.StackTrace);
                //Console.ReadKey();
                return(1);
            }
            Console.WriteLine("Completed");
            Console.ReadLine();
            return(0);
        }
        static int Main(string[] args)
        {
            //Параметры соответствуют вводу в форму RawtoMGF
            //args[0] - имя Raw-файла
            //args[1] - имя MGF-файла
            //args[2] - minimal MZ
            //args[3] - maximal MZ
            //args[4] - minimal RT
            //args[5] - maximal RT
            //args[6] - minimal Charge
            //args[7] - maximal Charge
            //args[8] - number of top peaks
            //args[9] - CleanETD:yes / CleanETD:no
            //args[10] - Instrument:yes / Instrument:no
            //дополнительно (к версии 2.0.6)
            //args[11] - CheckSpectra:yes / CheckSpectra:no
            try{
                Console.ReadLine();
                //Thread.Sleep(30000);
                string InFileName = args[0];
                string OutFileName = args[1];
                double MinMZ = Convert.ToDouble(args[2]);
                double MaxMZ = Convert.ToDouble(args[3]);
                double MinRT = Convert.ToDouble(args[4]);
                double MaxRT = Convert.ToDouble(args[5]);
                int MinCharge = Convert.ToInt32(args[6]);
                int MaxCharge = Convert.ToInt32(args[7]);
                int MaxPeakNumber = Convert.ToInt32(args[8]);
                bool CleanETD = args[9].Contains("CleanETD:yes");
                bool MarkInstrtument = args[10].Contains("Instrument:yes");
                bool CheckSpectra = args[11].Contains("CheckSpectra:yes");
                bool RTApex = args[12].Contains("RTApex:yes");

                string[] Refs = {"@cid","@hcd","@etd","@ecd","FTMS","ITMS"};

                MSFileReader_XRawfile RawFile;
                int Spectra,LocalCount = 0;
                string Filter;
                MGFFile MGF;
                MGFSpectrum ms;
                Childs ch;
                ChildbyIntensity ci = new ChildbyIntensity();
                ChildbyMass cm  = new ChildbyMass();

                int ArraySize = 0;
                Object MassList, EmptyRef;
                Object Labels,Values;
                double temp=0.0;
                int Progress = 0;
                int MSCount = 0;
                int MSMSCount = 0;

                if (RTApex){
                    MSFileBox = new RawFileBox();
                    MSFileBox.LoadIndex(InFileName);
                    RawFileBox.RepProgress = RepProgress;
                    RawFile = MSFileBox.RawFile;
                }else{
                    RawFile = new MSFileReader_XRawfile();
                    RawFile.Open(InFileName);
                    RawFile.SetCurrentController(0, 1);
                }
                Spectra = 0;
                RawFile.GetNumSpectra(ref Spectra);
                if (Spectra == 0) {
                    throw new Exception("Cannot get spectra from the file "+InFileName+", File is invalid, broken or empty");
                }
                MGF = new MGFFile();
                for (int j=1 ; j<=Spectra ; j++){
                    Filter = null;
                    RawFile.GetFilterForScanNum(j, ref Filter);
                    if (Filter.IndexOf("ms2") == -1) {
                        MSCount++;
                        if (!CheckSpectra){
                            continue;
                        }else{
                            ArraySize = 0;
                            MassList = null;
                            EmptyRef=null;
                            temp=0.0;
                            try {
                                RawFile.GetMassListFromScanNum(ref j, null, 0, 0, 0, 0,
                                    ref temp, ref MassList, ref EmptyRef, ref ArraySize);
                                continue;
                            }catch{
                                Exception e = new Exception(string.Format("Scan #{0} cannot be loaded, probably RAW file is corrupted!",j));
                                throw e;
                            }
                        }
                    }
                    MSMSCount++;
                    ms = new MGFSpectrum();
                    //определяем родительскую массу, заряд и RT
                    Labels = null;
                    Values = null;
                    ArraySize = 0;
                    LocalCount++;
                    RawFile.GetTrailerExtraForScanNum(j, ref Labels, ref Values, ref ArraySize);
                    for (int k = 0 ; k < ArraySize ; k++ ){
                        if ((Labels as Array).GetValue(k).ToString().Contains("Mono")){
                            ms.mz = Convert.ToDouble((Values as Array).GetValue(k).ToString());
                        }
                        if ((Labels as Array).GetValue(k).ToString().Contains("Charge State")){
                            ms.Charge = Convert.ToInt32((Values as Array).GetValue(k).ToString());
                        }
                    }
                    //Если не нашли в labels - берем из фильтра
                    if (ms.mz == 0.0) {
                        string  part= Filter.Substring(0,Filter.IndexOf('@'));
                        ms.mz = Convert.ToDouble(part.Substring(part.LastIndexOf(' ')));
                    }
                    Labels = null;
                    Values = null;
                    ArraySize = 0;
                    double RT = 0;
                    RawFile.GetStatusLogForScanNum(j,ref RT, ref Labels, ref Values, ref ArraySize);

                    RawFile.RTFromScanNum(j,ref ms.RT);
                    ms.ScanNumber = j;
                    //Фильтры
                    if (ms.Charge < MinCharge) continue;
                    if (ms.Charge > MaxCharge) continue;
                    if (ms.RT < MinRT) continue;
                    if (MaxRT != 0.0 && ms.RT > MaxRT) continue;
                    if (ms.mz < MinMZ) continue;
                    if (MaxMZ != 0.0 && ms.mz > MaxMZ) continue;
                    //забираем сам спектр
                    MassList = null;
                    EmptyRef=null;
                    ArraySize = 0;
                    temp=0.0;
                    try{
                        if (Filter.IndexOf("FTMS") != -1){
                            //извлекаем FTMS данные
                            (RawFile as IXRawfile2).GetLabelData(ref MassList, ref EmptyRef, ref  j);
                            ArraySize = (MassList as Array).GetLength(1);
                            for (int k = 0 ; k<ArraySize ; k++ ){
                                ch = new Childs();
                                ch.Mass = (double)(MassList as Array).GetValue(0, k);
                                ch.Intensity = (double)(MassList as Array).GetValue(1, k);
                                ms.Data.Add(ch);
                            }
                        }else{
                            //извлекаем ITMS данные
                            RawFile.GetMassListFromScanNum(ref j, null, 0, 0, 0, 1, ref temp, ref MassList, ref EmptyRef, ref ArraySize);
                            ArraySize = (MassList as Array).GetLength(1);
                            for ( int k = 0 ; k<ArraySize ; k++){
                                ch = new Childs();
                                ch.Mass = (double)(MassList as Array).GetValue(0, k);
                                ch.Intensity = (double)(MassList as Array).GetValue(1, k);
                                ms.Data.Add(ch);
                            }
                        }
                    }catch{
                        Exception e = new Exception(string.Format("Scan #{0} cannot be loaded, probably RAW file is corrupted!",j));
                        throw e;
                    }
                    if (RTApex){
                        ms.RTApex = CheckRTApex(ms.RT, ms.mz);
                    }

                    if (MarkInstrtument){
                        if (Filter.Contains("ecd") || Filter.Contains("etd")){
                                ms.Instrument = "ETD-TRAP";
                            }else{
                                ms.Instrument= "ESI-FTICR";
                            }
                        }
                    //очистить ETD если был такой запрос
                    if ( CleanETD ){
                        if (Filter.Contains("ecd") || Filter.Contains("etd")){
                            FilterETD(ref ms,  Filter.Contains("FTMS"));
                        }
                    }
                    //сбросить лишние сигналы
                    if (MaxPeakNumber > 0 && ms.Data.Count > MaxPeakNumber){
                        ms.Data.Sort(ci);
                        ms.Data.RemoveRange(0,ms.Data.Count-MaxPeakNumber);
                        ms.Data.Sort(cm);
                    }
                    //сформировать TITLE
                    if (RTApex){
                        ms.Title = String.Format("Elution from: {0:f4} to {0:f4} RT Apex: {1:f2} FinneganScanNumber: {2}",
                            ms.RT, ms.RTApex, ms.ScanNumber);
                    }else{
                        ms.Title = String.Format("Elution from: {0:f4} to {0:f4} FinneganScanNumber: {1}",
                            ms.RT,ms.ScanNumber);
                    }
                    MGF.Spectra.Add(ms);
                    // рапортовать прогресс
                    GC.Collect(2);

                    if ((int)(((double)j/(double)Spectra)*100.0) > Progress){
                        Progress = (int)(((double)j/(double)Spectra)*100.0);
                        Console.WriteLine("{0}%... {1} {2}",Progress,MSCount,MSMSCount);
                    }

                    //backgroundWorker1.ReportProgress((int)(((double)LocalCount/(double)SpCount)*100.0));
                }
                MGF.MGFComments.Add(String.Format("Created by RawToMGF 2.1.3; Spectra obtained from {0}",InFileName));
                MGF.MGFComments.Add(String.Format("Filters: Parent m/z from {0} Th to {1} Th;",MinMZ,MaxMZ));
                MGF.MGFComments.Add(String.Format("         RT from {0} min. to {1} min.;",MinRT,MaxRT));
                MGF.MGFComments.Add(String.Format("         Charge state of parent ions minimum {0}, maximum {1};",MinCharge,MaxCharge));
                MGF.MGFComments.Add(String.Format("         Max number of peaks in MS/MS spectra - {0}",MaxPeakNumber));
                if ( CleanETD ) {
                    MGF.MGFComments.Add("         ETD spectra cleaned from precursors and neutral losses");
                }
                MGF.MGFWrite(OutFileName,true);
            }catch(Exception e){
                Console.Write("Error:");
                Console.Write(e.Message);
                Console.WriteLine("STACKINFO:"+e.StackTrace);
                //Console.ReadKey();
                return 1;
            }
            Console.WriteLine("Completed");
            Console.ReadLine();
            return 0;
        }
        private void DoWork()
        {
            //проверка параметров
            try{
                PPMs              = Convert.ToDouble(Settings.Default.MassDev);
                RTPerc            = Convert.ToDouble(Settings.Default.RTDevProc);
                RTMin             = Convert.ToDouble(Settings.Default.RTDevMin);
                MS2Acc            = Convert.ToDouble(Settings.Default.MS2Da);
                FrMatch           = Convert.ToInt32(Settings.Default.MS2PeakMatches);
                SpectraPerCluster = Convert.ToInt32(Settings.Default.SpecPerClust);
            }catch {
                MessageBox.Show("Parametrs must be set.");
            }

            //открываем себе файл для выборочного лога
            //StreamWriter SW = new StreamWriter("log.log");
            //загрузка данных
            Files           = new MGFFile[MGFlist.Items.Count];
            FileCount       = MGFlist.Items.Count;
            ProgressMessage = "Loading data...";
            for (int i = 0; i < FileCount; i++)
            {
                Files[i] = new MGFFile();
                Files[i].MGFRead(MGFlist.Items[i].ToString());
                Progress(i, FileCount);
                //если есть информация по RT Apex - используем ее
                for (int j = 0; j < Files[i].Spectra.Count; j++)
                {
                    if (Files[i].Spectra[j].RTApex != 0.0)
                    {
                        Files[i].Spectra[j].RT = Files[i].Spectra[j].RTApex;
                    }
                }
            }

            int WorkerThreads, IOThreads;

            ThreadPool.GetMaxThreads(out WorkerThreads, out IOThreads);
            WorkerThreads = Environment.ProcessorCount;
            ThreadPool.SetMaxThreads(WorkerThreads, IOThreads);

            //Очистка лишних сигналов

            try{
                MISignals = Convert.ToInt32(Settings.Default.MS2PeaksNumber);
            }catch { MISignals = 0; }


            SpectrabyRT sr = new SpectrabyRT();

            for (int i = 0; i < FileCount; i++)
            {
                Files[i].Spectra.Sort(sr);
            }

            //Собираем консенсусный набор спектров
            //матчинг спектров - нетранзитивен!!
            Aligners = new List <Aligner>();

            //Матчинг внутри файла
            MatchedFiles = new List <MGFMatched> [FileCount];
            int LocalCount;

            ProgressMessage = "Intermal Spectra Matching...";
            ExecCount       = 0;
            for (int i = 0; i < FileCount; i++)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(SingleFileMatching), new IntArg(i));
            }
            while (true)
            {
                lock (ForCountLock){
                    LocalCount = ExecCount;
                }
                Thread.Sleep(200);
                Progress(LocalCount, Files.GetLength(0));
                if (LocalCount >= Files.GetLength(0))
                {
                    break;
                }
            }

            /*for (int i = 0 ; i < FileCount ; i++ ){
             *  MatchedFiles[i] = SingleFileMatching(i);
             * }*/

            //соединяем и сортируем по времени выхода
            for (int i = 0; i < FileCount; i++)
            {
                Merged.AddRange(MatchedFiles[i]);
            }
            Merged.Sort(new MGFMatched.MatchedByRT());
            MaxRT = Merged[Merged.Count - 1].Spectrum.RT;

            //сматчивем горизонтально в три прослойки (операционное поле, буфер спереди, буфер сзади)
            ProgressMessage = "External Spectra Matching...";
            int SliceCount = Convert.ToInt32(Math.Floor(MaxRT / RTMin)) + 1;

            ExecCount = 0;
            for (int i = 0; i < SliceCount; i += 3)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(HorizontalMatching), new DoubleArg(RTMin * i));
            }
            while (true)
            {
                lock (ForCountLock){
                    LocalCount = ExecCount;
                }
                Thread.Sleep(200);
                Progress(LocalCount, SliceCount);
                if (LocalCount == ((SliceCount - 1) / 3) + 1)
                {
                    break;
                }
            }

            for (int i = 1; i < SliceCount; i += 3)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(HorizontalMatching), new DoubleArg(RTMin * i));
            }
            while (true)
            {
                lock (ForCountLock){
                    LocalCount = ExecCount;
                }
                Thread.Sleep(200);
                Progress(LocalCount, SliceCount);
                if (LocalCount == (((SliceCount - 1) / 3) + 1) + ((SliceCount - 2) / 3 + 1))
                {
                    break;
                }
            }

            for (int i = 2; i < SliceCount; i += 3)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(HorizontalMatching), new DoubleArg(RTMin * i));
            }
            while (true)
            {
                lock (ForCountLock){
                    LocalCount = ExecCount;
                }
                Thread.Sleep(200);
                Progress(LocalCount, SliceCount);
                if (LocalCount >= SliceCount)
                {
                    break;
                }
            }

/*            for(int i=0 ; i<SliceCount ; i+=3){
 *              HorizontalMatching(new DoubleArg(RTMin * i));
 *          }
 *          for(int i=1 ; i<SliceCount ; i+=3){
 *              HorizontalMatching(new DoubleArg(RTMin * i));
 *          }
 *          for(int i=2 ; i<SliceCount ; i+=3){
 *              HorizontalMatching(new DoubleArg(RTMin * i));
 *          }*/

            Aligner Al;

            for (int i = 0; i < Merged.Count; i++)
            {
                if (Merged[i] != null)
                {
                    Al         = new Aligner();
                    Al.Best    = Merged[i].Spectrum;
                    Al.Origin  = Merged[i].Origin;
                    Al.Indexes = new int[FileCount];
                    for (int j = 0; j < FileCount; j++)
                    {
                        Al.Indexes[j] = -1;
                    }
                    Al.Indexes[Al.Origin] = Merged[i].Index;
                    foreach (MGFMatched M in Merged[i].InterMatched)
                    {
                        Al.Indexes[M.Origin] = M.Index;
                    }
                    Al.SignChanged = false;
                    Aligners.Add(Al);
                }
            }

            //собственно выравнивание
            //??? - В каком порядке исходно стоят алигнеры
            int Count;

            //оцениваем расстояние и количество спектров
            ProgressMessage = "Estimating spectra distance...";
            ExecCount       = 0;
            for (int i = 0; i < Aligners.Count; i += 1000)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(DistanceEst), new IntArg(i));
            }
            while (true)
            {
                lock (ForCountLock){
                    LocalCount = ExecCount;
                }
                Thread.Sleep(200);
                Progress(LocalCount, (Aligners.Count - 1) / 1000 + 1);
                if (LocalCount >= (Aligners.Count - 1) / 1000 + 1)
                {
                    break;
                }
            }


            //подвид пузырьковой сортировки
            //нарезаем кусочки по RTMin
            Slices = new int[SliceCount];
            Count  = 0;
            for (int i = 0; i < Aligners.Count; i++)
            {
                if (Aligners[i].Best.RT >= ((double)(Count) * RTMin))
                {
                    Slices[Count] = i;
                    Count++;
                }
            }

            ProgressMessage = "Aligning spectra...";
            int UpperIndex, LowerIndex;

            for (int i = 0; i < SliceCount; i++) //максимальная процедура - на квадрат
            {
                bool flag = true;
                Count     = 0;
                ExecCount = 0;
                for (int j = i % 2; j < SliceCount; j += 2)
                {
                    UpperIndex = Slices[j];
                    if (j + 2 < SliceCount)
                    {
                        LowerIndex = Slices[j + 2];
                    }
                    else
                    {
                        LowerIndex = Aligners.Count;
                    }
                    int k;
                    for (k = UpperIndex; k < LowerIndex; k++)
                    {
                        if (!Aligners[k].SignChanged)
                        {
                            break;
                        }
                    }
                    if (k < LowerIndex)
                    {
                        ThreadPool.QueueUserWorkItem(new WaitCallback(Arrange), new IntArg(j));
                        //Arrange(new IntArg(j));
                        Count++;
                        flag = false;
                    }
                }
                while (true)
                {
                    lock (ForCountLock){
                        LocalCount = ExecCount;
                    }
                    Thread.Sleep(200);
                    Progress(SliceCount - Count, SliceCount);
                    if (LocalCount >= Count)
                    {
                        break;
                    }
                }

                if (flag)
                {
                    break;
                }
            }


            ProgressMessage = "Writing spectra...";
            Progress(0, 100);

            //Меняем FSN в Title - сообразно новому порядку
            for (int i = 0; i < Aligners.Count; i++)
            {
                string Title = Aligners[i].Best.Title;
                if (Title.Contains("Origin"))  //затычка на повторное включение спектра в коллекцию
                {
                    Aligners[i].Best.Title = null;
                    continue;
                }
                Title = Title.Replace("FinneganScanNumber:",
                                      String.Format("Origin: {0} Order: {1} FinneganScanNumber:",
                                                    Path.GetFileName(MGFlist.Items[Aligners[i].Origin].ToString()), i));
                Aligners[i].Best.Title = Title;
                Aligners[i].Best.Data.Sort(new ChildbyMass());
            }


            //выводим конечную коллекцию
            //for (SpectraPerCluster = 1 ; SpectraPerCluster<48 ; SpectraPerCluster++){
            MGFFile OutFile = new MGFFile();

            for (int i = 0; i < Aligners.Count; i++)
            {
                if (Aligners[i].Best.Title == null)
                {
                    continue;
                }
                //считаем наличные индексы
                int IndexCount = 0;
                for (int j = 0; j < FileCount; j++)
                {
                    if (Aligners[i].Indexes[j] != -1)
                    {
                        IndexCount++;
                    }
                }
                if (IndexCount >= SpectraPerCluster)
                {
                    OutFile.Spectra.Add(Aligners[i].Best);
                }
            }
            //формируем комментарий
            string Comment = Text + "; Consensus MGF aligned from :";

            for (int i = 0; i < FileCount; i++)
            {
                Comment += MGFlist.Items[i].ToString() + ", ";
            }
            OutFile.MGFComments.Add(Text);
            OutFile.MGFComments.Add(String.Format("MS Tol.: {0} ppm, MS/MS Tol: {1} Da, RT Deviation {2} min., Minimum {3} peaks of top {4} matched.",
                                                  MassDevBox.Text, MS2DaBox.Text, RTMinBox.Text, textBox8.Text, MS2PeaksBox.Text));
            OutFile.MGFComments.Add("Source files:");
            for (int i = 0; i < FileCount; i++)
            {
                OutFile.MGFComments.Add(MGFlist.Items[i].ToString());
            }
            OutFile.MGFComments.Add(String.Format("Consensus MGF aligned from {0} files", FileCount));
            OutFile.MGFWrite(OutMgfBox.Text /*+SpectraPerCluster.ToString()*/);
            //}

            Progress(100, 100);
            //SW.Close();
            ProgressMessage = "Processing completed...";
            SystemSounds.Beep.Play();
        }