/// <summary>
        /// Search for pixel number for the input wavelength
        /// </summary>
        /// <param name="lambda">wavelength</param>
        /// <param name="order">order</param>
        /// <param name="bord1">left bound of searching window</param>
        /// <param name="bord2">right bound of searching window</param>
        /// <param name="error">error of computations</param>
        /// <returns>pixel number</returns>
        public static double FindPix(double lambda, int order, double bord1, double bord2, double error, int x_trim_left)
        {
            double diff, f1, fc, center;

            do
            {
                center = 0.5 * (bord1 + bord2);
                f1     = EcheData.GetWL(order, bord1, x_trim_left) - lambda;
                fc     = EcheData.GetWL(order, center, x_trim_left) - lambda;
                if (f1 * fc > 0)
                {
                    bord1 = center;
                }
                else
                {
                    bord2 = center;
                }
                diff = Math.Abs(bord2 - bord1);
            } while (diff > error);
            return((bord2 + bord1) * 0.5);
        }
        public static void Calibrate(double[][] fluxes, int oo, int ox, double cutLimit, int iterMax, double fluxLimit, int x_trim_left)
        {
            int orders_count = fluxes.Length;
            int pixels_count = fluxes[0].Length;

            double[] point_order   = new double[5000];
            double[] point_lambda  = new double[5000];
            double[] point_pixel   = new double[5000];
            int      points_number = 0;

            Console.WriteLine("Repers identification...");

            // repers identification cycle;
            Console.Write("Search in orders: ");
            for (int order = 0; order < orders_count; order++)
            {
                Console.Write("[{0}]", order);
                double   wbegin     = EcheData.GetWL(order, 0, x_trim_left);
                double   wend       = EcheData.GetWL(order, pixels_count - 1, x_trim_left);
                double[] cur_fluxes = new double[pixels_count];
                double   tmx        = 0;
                for (int i = 0; i < pixels_count; i++)
                {
                    cur_fluxes[i] = fluxes[order][i];
                    if (cur_fluxes[i] > tmx)
                    {
                        tmx = cur_fluxes[i];
                    }
                }
                for (int i = 0; i < pixels_count; i++)
                {
                    cur_fluxes[i] = cur_fluxes[i] / tmx;
                }

                int n_atlas = ThAr.Wls.Length;

                int      lines_count = 0;
                double[] lines_wavls = new double[n_atlas];
                for (int i = 0; i < n_atlas; i++)
                {
                    if (wbegin > wend)  // smaller pixels numbers corresponded largest wavelengths
                    {
                        if (ThAr.Wls[i] < wbegin)
                        {
                            if (ThAr.Wls[i] > wend)
                            {
                                lines_wavls[lines_count] = ThAr.Wls[i];
                                lines_count++;
                            }
                        }
                    }
                    else
                    {
                        if (ThAr.Wls[i] > wbegin)
                        {
                            if (ThAr.Wls[i] < wend)
                            {
                                lines_wavls[lines_count] = ThAr.Wls[i];
                                lines_count++;
                            }
                        }
                    }
                }

                Array.Resize(ref lines_wavls, lines_count);

                int swin  = 6;
                int shift = 0;

                for (int i = 0; i < lines_count; i++)
                {
                    double pix = FindPix(lines_wavls[i], order, 0, pixels_count - 1, 0.001, x_trim_left);
                    int    k1  = (int)pix - swin + shift;
                    int    k2  = (int)pix + swin + shift;
                    if (k1 < 1)
                    {
                        k1 = 1;
                    }
                    if (k2 > pixels_count - 2)
                    {
                        k2 = pixels_count - 2;
                    }
                    double max   = 0;
                    int    j_max = 0;
                    for (int j = k1; j <= k2; j++)
                    {
                        if (cur_fluxes[j] > cur_fluxes[j - 1] && cur_fluxes[j] > cur_fluxes[j + 1])
                        {
                            if (cur_fluxes[j] > max)
                            {
                                max   = cur_fluxes[j];
                                j_max = j;
                            }
                        }
                    }
                    if (max * tmx > fluxLimit)
                    {
                        //Saver.SaveColumn(cur_fluxes, "CURR.txt");

                        k1 = j_max - 4;
                        k2 = j_max + 4;
                        if (k1 < 0)
                        {
                            k1 = 0;
                        }
                        if (k2 > pixels_count - 1)
                        {
                            k2 = pixels_count - 1;
                        }
                        double[] x = new double[k2 - k1 + 1];
                        double[] y = new double[k2 - k1 + 1];
                        int      l = 0;
                        for (int k = k1; k <= k2; k++)
                        {
                            x[l] = (double)k;
                            y[l] = cur_fluxes[k];
                            l++;
                        }
                        //double center = GravCenter(x, y);
                        double center = GravCenterSpline(x, y);

                        point_lambda[points_number] = lines_wavls[i];
                        point_order[points_number]  = order;
                        point_pixel[points_number]  = center;
                        points_number++;
                    }
                }
            }
            Console.Write("\r\n");
            Console.WriteLine("{0} repers were found.", points_number);

            Array.Resize(ref point_lambda, points_number);
            Array.Resize(ref point_order, points_number);
            Array.Resize(ref point_pixel, points_number);

            for (int i = 0; i < points_number; i++)
            {
                point_order[i]++;
            }
            for (int i = 0; i < points_number; i++)
            {
                point_order[i] = point_order[i] / orders_count;
            }
            for (int i = 0; i < points_number; i++)
            {
                point_pixel[i] = point_pixel[i] / pixels_count;
            }
            for (int i = 0; i < points_number; i++)
            {
                point_lambda[i] = point_lambda[i] / 7000;
            }

            double[] coeff = null;
            double   stderror;
            int      rejected_poins_number = 0;

            Console.Write("Iterations: ");
            for (int i = 0; i < iterMax; i++)
            {
                Console.Write("[{0}]", i + 1);
                coeff    = Fitting(point_order, point_pixel, point_lambda, oo, ox);
                stderror = 0;
                for (int j = 0; j < points_number; j++)
                {
                    stderror += Math.Pow(point_lambda[j] - Surface(coeff, point_order[j], point_pixel[j], oo, ox), 2);
                }
                stderror = Math.Sqrt(stderror / points_number);
                double diff;
                int    k = 0;
                for (int j = 0; j < points_number; j++)
                {
                    diff = Math.Abs(point_lambda[j] - Surface(coeff, point_order[j], point_pixel[j], oo, ox));
                    if (diff < cutLimit * stderror)
                    {
                        point_lambda[k] = point_lambda[j];
                        point_order[k]  = point_order[j];
                        point_pixel[k]  = point_pixel[j];
                        k++;
                    }
                    else
                    {
                        rejected_poins_number++;
                    }
                }
                points_number = k;
            }
            Console.WriteLine("\r\n{0} points were rejected.", rejected_poins_number);

            double[] diffs = new double[points_number];
            stderror = 0;
            for (int j = 0; j < points_number; j++)
            {
                diffs[j]  = point_lambda[j] * 7000 - 7000 * Surface(coeff, point_order[j], point_pixel[j], oo, ox);
                stderror += diffs[j] * diffs[j];
            }
            stderror = Math.Sqrt(stderror / points_number);
            Console.WriteLine("Std. Error: {0:0.000E00}", stderror);

            System.IO.StreamWriter sw = new System.IO.StreamWriter((string)Init.Value("DIR_MAIN") + "\\found_repers.dat");
            for (int i = 0; i < points_number; i++)
            {
                sw.WriteLine("{0}\t{1}\t{2}\t{3}", point_order[i] * orders_count - 1, point_pixel[i] * pixels_count, point_lambda[i] * 7000, diffs[i]);
            }
            sw.Close();

            Lambdas = new double[orders_count][];
            for (int i = 0; i < orders_count; i++)
            {
                Lambdas[i] = new double[pixels_count];
            }

            for (int order = 1; order <= orders_count; order++)
            {
                for (int p = 0; p < pixels_count; p++)
                {
                    int    k   = 0;
                    double sum = 0;
                    for (int i = 0; i <= oo; i++)
                    {
                        for (int j = 0; j <= ox; j++)
                        {
                            sum += coeff[k] * Math.Pow((double)order / orders_count, i) *
                                   Math.Pow((double)p / pixels_count, j);
                            k++;
                        }
                    }
                    Lambdas[order - 1][p] = sum * 7000;
                }
            }
        }