/// <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 Locate(ref Image im, int polynom_degree) { double[] order_centers = new double[2]; int wing = 2; int middle = im.NAXIS2 / 2; Image slice = new Image(im.NAXIS1, 1 + 2 * wing); for (int i = 0; i < slice.NAXIS1; i++) { for (int j = 0; j < slice.NAXIS2; j++) { slice[i, j] = im[i, middle - wing + j]; } } double[] aver_column = new double[im.NAXIS1]; for (int i = 0; i < aver_column.Length; i++) { aver_column[i] = Statistics.Median(slice.GetRow(i)); } StreamWriter sw = new StreamWriter((string)Init.Value("DIR_MAIN") + "\\Slice.txt"); for (int i = 0; i < aver_column.Length - 1; i++) { sw.WriteLine("{0}\t{1}", i, aver_column[i].ToString()); } sw.Close(); // Search for orders locations in cetral slit; double[] xmax_0 = new double[5000]; int orders_count = 0; int dist = 5; // for ZTSh EcheData.LoadOrdMidPos("OrdPos.dat", (int)Init.Value("TRIM_COL1")); double[] xmax = new double[EcheData.ord_mid_pos.Length]; for (int i = 0; i < xmax.Length; i++) { xmax[i] = (double)EcheData.ord_mid_pos[i]; } for (int i = 0; i < xmax.Length; i++) { int x1 = (int)xmax[i] - dist; int x2 = (int)xmax[i] + dist; if (x1 < 0) { x1 = 0; } if (x2 > aver_column.Length - 1) { x2 = aver_column.Length - 1; } int xm = x1; double max = aver_column[x1]; for (int j = x1 + 1; j <= x2; j++) { if (aver_column[j] > max) { max = aver_column[j]; xm = j; } } xmax[i] = xm; } orders_count = xmax.Length; // Orders Tracing; pos_ord = new double[orders_count][]; for (int i = 0; i < pos_ord.Length; i++) { pos_ord[i] = new double[im.NAXIS2]; } for (int i = 0; i < pos_ord.Length; i++) { pos_ord[i][middle] = xmax[i]; } int nwin = 8; int o1 = 0, o2 = 0; for (int i = middle - 1; i >= 0; i--) { for (int n = o1; n < orders_count + o2; n++) { int n1 = (int)pos_ord[n][i + 1] - nwin; int n2 = (int)pos_ord[n][i + 1] + nwin; double max = 0; for (int k = n1; k <= n2; k++) { if (im[k, i] > max) { pos_ord[n][i] = k; max = im[k, i]; } } } } for (int i = middle + 1; i < im.NAXIS2; i++) { for (int n = o1; n < orders_count + o2; n++) { int n1 = (int)pos_ord[n][i - 1] - nwin; int n2 = (int)pos_ord[n][i - 1] + nwin; double max = 0; for (int k = n1; k <= n2; k++) { if (im[k, i] > max) { pos_ord[n][i] = k; max = im[k, i]; } } } } pos_min = new double[pos_ord.Length + 1][]; for (int i = 0; i < pos_min.Length; i++) { pos_min[i] = new double[im.NAXIS2]; } for (int i = 0; i < im.NAXIS2; i++) { for (int n = 1; n < pos_min.Length - 1; n++) { int n1 = (int)pos_ord[n - 1][i]; int n2 = (int)pos_ord[n][i]; double min = double.MaxValue; for (int k = n1; k <= n2; k++) { if (im[k, i] < min) { pos_min[n][i] = k; min = im[k, i]; } } } } for (int i = 0; i < im.NAXIS2; i++) { pos_min[0][i] = pos_min[1][i] - (pos_min[2][i] - pos_min[1][i]); if (pos_min[0][i] < 0) { pos_min[0][i] = 0; } } for (int i = 0; i < im.NAXIS2; i++) { pos_min[pos_min.Length - 1][i] = pos_min[pos_min.Length - 2][i] + (pos_min[pos_min.Length - 2][i] - pos_min[pos_min.Length - 3][i]); if (pos_min[pos_min.Length - 1][i] > aver_column.Length - 1) { pos_min[pos_min.Length - 1][i] = aver_column.Length - 1; } } Saver.SaveOrderedDistribution(pos_min, (string)Init.Value("DIR_MAIN") + "\\trace_min.txt"); Saver.SaveColumn(xmax, (string)Init.Value("DIR_MAIN") + "\\orders_ident.dat"); double[] pixels_x = new double[im.NAXIS2]; for (int i = 0; i < pixels_x.Length; i++) { pixels_x[i] = i; } GravImprove(im, ref pos_min, ref pos_ord); Saver.SaveOrderedDistribution(pos_ord, (string)Init.Value("DIR_MAIN") + "\\trace.txt"); for (int i = 0; i < pos_ord.Length; i++) { ImproveTraces(pixels_x, ref pos_ord[i], polynom_degree); } for (int i = 0; i < pos_min.Length; i++) { ImproveTraces(pixels_x, ref pos_min[i], polynom_degree); } Saver.SaveOrderedDistribution(pos_ord, (string)Init.Value("DIR_MAIN") + "\\orders_impoved.dat"); Saver.SaveOrderedDistribution(pos_min, (string)Init.Value("DIR_MAIN") + "\\mins_improved.dat"); for (int i = 0; i < xmax.Length; i++) { xmax[i] = pos_ord[i][middle]; } Saver.SaveColumn(xmax, (string)Init.Value("DIR_MAIN") + "\\Orders.txt"); }
static void Main(string[] args) { Console.Beep(); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("*******************************************************"); Console.WriteLine("* MERCATOR/HERMES *"); Console.WriteLine("* SPECTRA REDUCTION PIPELINE *"); Console.WriteLine("*******************************************************"); Console.ForegroundColor = ConsoleColor.White; //Image.Save("file.fit"); //goto STOP; //InitFile.ReadInitFile("INIT.dat"); Init.Initialize("INIT.dat"); if (Init.ErrorString != "") { Console.WriteLine("Error in INIT file!"); Console.WriteLine(Init.ErrorString); goto STOP; } string dir_main = (string)Init.Value("DIR_MAIN"); if (!Directory.Exists(dir_main)) { try { Directory.CreateDirectory(dir_main); } catch { Console.WriteLine("Cannot create main directory.\r\n"); goto STOP; } } string[] bias_files = null, flat_files = null, thar_files = null, obj_files = null; Console.WriteLine("Searching for Bias, Flat, ThAr and Object files..."); try { bias_files = ImageSelector.GetFilesByHDU( (string)Init.Value("DIR_BIAS"), (string)Init.Value("FMASK_BIAS"), "IMAGETYP", "*"); flat_files = ImageSelector.GetFilesByHDU( (string)Init.Value("DIR_FLAT"), (string)Init.Value("FMASK_FLAT"), "IMAGETYP", "*"); thar_files = ImageSelector.GetFilesByHDU( (string)Init.Value("DIR_CLBR"), (string)Init.Value("FMASK_CLBR"), "IMAGETYP", "*"); obj_files = ImageSelector.GetFilesByHDU( (string)Init.Value("DIR_OBJ"), (string)Init.Value("FMASK_OBJ"), "IMAGETYP", "*"); } catch { Console.WriteLine("Error in files searching..."); goto STOP; } Console.WriteLine("Bias files number: {0}", bias_files.Length); Console.WriteLine("Flat files number: {0}", flat_files.Length); Console.WriteLine("ThAr files number: {0}", thar_files.Length); Console.WriteLine("Object files number: {0}", obj_files.Length); if (bias_files.Length == 0 || flat_files.Length == 0 || thar_files.Length == 0 || obj_files.Length == 0) { Console.WriteLine("Some necessary files were not found..."); goto STOP; } Image[] biases = new Image[bias_files.Length]; Image[] flats = new Image[flat_files.Length]; Image[] thars = new Image[thar_files.Length]; Image[] objects = new Image[obj_files.Length]; // Loading and averaging of bias images; Console.WriteLine("Loading Bias images..."); for (int i = 0; i < bias_files.Length; i++) { Console.WriteLine("->" + bias_files[i]); biases[i] = new Image(); biases[i].LoadImage(bias_files[i]); if ((bool)Init.Value("TRIM_ON")) { biases[i] = biases[i].Trim( (int)Init.Value("TRIM_STR1"), (int)Init.Value("TRIM_COL1"), (int)Init.Value("TRIM_STR2"), (int)Init.Value("TRIM_COL2")); } //Console.WriteLine("MEAN = {0:0.00}; STDDEV = {1:0.00}", // Statistics.Mean(biases[i]), Statistics.StdDev(biases[i])); } Console.WriteLine("Bias images averaging..."); Image bias_aver = ImageCombinator.Median(biases); for (int i = 0; i < bias_files.Length; i++) { biases[i] = null; } // Loading and averaging of flat images; Console.WriteLine("Loading Flat images..."); for (int i = 0; i < flat_files.Length; i++) { Console.WriteLine("->" + flat_files[i]); flats[i] = new Image(); flats[i].LoadImage(flat_files[i]); if ((bool)Init.Value("TRIM_ON")) { flats[i] = flats[i].Trim( (int)Init.Value("TRIM_STR1"), (int)Init.Value("TRIM_COL1"), (int)Init.Value("TRIM_STR2"), (int)Init.Value("TRIM_COL2")); } } Console.WriteLine("Flat images averaging..."); Image flat_aver = ImageCombinator.Median(flats); for (int i = 0; i < flat_files.Length; i++) { flats[i] = null; } // Loading and averaging of Th-Ar images; Console.WriteLine("Loading Th-Ar images..."); for (int i = 0; i < thar_files.Length; i++) { Console.WriteLine("->" + thar_files[i]); thars[i] = new Image(); thars[i].LoadImage(thar_files[i]); if ((bool)Init.Value("TRIM_ON")) { thars[i] = thars[i].Trim( (int)Init.Value("TRIM_STR1"), (int)Init.Value("TRIM_COL1"), (int)Init.Value("TRIM_STR2"), (int)Init.Value("TRIM_COL2")); } } Console.WriteLine("ThAr images averaging..."); Image Thar_aver = ImageCombinator.Median(thars); for (int i = 0; i < thar_files.Length; i++) { thars[i] = null; } Console.WriteLine("Bias subtraction from averanged Flat image..."); Image flat_aver_db = new Image(); flat_aver_db = flat_aver - bias_aver; Console.WriteLine("Bias subtraction from averanged ThAr image..."); Image Thar_aver_db = Thar_aver - bias_aver; //Console.WriteLine("Replasing pixels values:\r\n negative -> 1 for flat;\r\n negative -> 0 for Th-Ar;"); for (int i = 0; i < flat_aver_db.NAXIS1; i++) { for (int j = 0; j < flat_aver_db.NAXIS2; j++) { if (flat_aver_db[i, j] <= 0) { flat_aver_db[i, j] = 1; } if (Thar_aver_db[i, j] < 0) { Thar_aver_db[i, j] = 0; } } } Console.WriteLine("Search for order locations..."); flat_aver_db.Tr(); int polinim_degree_order = 3; Locator.Locate(ref flat_aver_db, polinim_degree_order); double[][] pos_ord = Locator.Ord_Pos; double[][] pos_min = Locator.Min_Pos; double[][] fluxes; // Flat spectra extraction; Console.WriteLine("Extraction of the flat spectra..."); int bkg_mode = (int)Init.Value("BKG_MODE"); int aperture_wing = (int)Init.Value("APER_WING"); int bkg_oo = 0, bkg_ox = 0, bkg_sw = 0, bkg_step = 0; if (bkg_mode == 0) { bkg_sw = (int)Init.Value("BKG_SW"); Extractor.ExtractMode1(flat_aver_db, pos_ord, pos_min, aperture_wing, bkg_sw); } if (bkg_mode == 1) { bkg_sw = (int)Init.Value("BKG_SW"); bkg_oo = (int)Init.Value("BKG_OO"); bkg_ox = (int)Init.Value("BKG_OX"); bkg_step = (int)Init.Value("BKG_STEP"); Image bkg_im = Background.Fit(flat_aver_db, pos_min, bkg_ox, bkg_oo, bkg_sw, bkg_step); Extractor.ExtractMode2(flat_aver_db, bkg_im, pos_ord, pos_min, aperture_wing); } fluxes = Extractor.FluxDebiased; Saver.SaveOrderedDistribution(fluxes, dir_main + "\\Flat_Orders.dat"); Saver.SaveOrderedDistribution(Extractor.fluxes_min_init, dir_main + "\\BKG_FLAT.DAT"); Saver.SaveOrderedDistribution(Extractor.fluxes_min_smoothed, dir_main + "\\BKG_SMOOTH_FLAT.DAT"); // Flat spectra normalization; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Flat spectra normalization..."); Console.ForegroundColor = ConsoleColor.White; Normator.Norm(fluxes, 12, 0, 13); Saver.SaveOrderedDistribution(Normator.OrdersNorm, dir_main + "\\Flat_Orders_Norm.dat"); Saver.SaveOrderedDistribution(Normator.FitCurves, dir_main + "\\Flat_Orders_Fit.dat"); // Th-Ar spectra extraction; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Extraction of the Th-Ar spectrum..."); Console.ForegroundColor = ConsoleColor.White; Thar_aver_db.Tr(); if (bkg_mode == 0) { Extractor.ExtractMode1(Thar_aver_db, pos_ord, pos_min, aperture_wing, bkg_sw); } if (bkg_mode == 1) { Image bkg_im = Background.Fit(flat_aver_db, pos_min, bkg_ox, bkg_oo, bkg_sw, bkg_step); Extractor.ExtractMode2(Thar_aver_db, bkg_im, pos_ord, pos_min, aperture_wing); } fluxes = Extractor.FluxDebiased; Saver.SaveOrderedDistribution(fluxes, dir_main + "\\thar_extacted.txt"); // Wavelength calibration; double[][] lambdas; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Wavelength calibration..."); Console.ForegroundColor = ConsoleColor.White; EcheData.LoadDispCurves("CalibrationCurves.dat"); int oo = (int)Init.Value("WAVE_OO"); int ox = (int)Init.Value("WAVE_OX"); int iterNum = (int)Init.Value("WAVE_NINER"); double cutLimit = (double)Init.Value("WAVE_REJ"); double fluxLimit = (double)Init.Value("WAVE_THRESH"); Console.WriteLine("OO = {0}; OX = {1}; Reject = {2}; IterNum = {3}; FluxLimit = {4}", oo, ox, cutLimit, iterNum, fluxLimit); int x_trim_left = 0; if ((bool)Init.Value("TRIM_ON")) { x_trim_left = (int)Init.Value("TRIM_STR1"); } WLCalibration.Calibrate(fluxes, oo, ox, cutLimit, iterNum, fluxLimit, x_trim_left); lambdas = WLCalibration.Lambdas; Saver.SaveOrderedDistribution(lambdas, dir_main + "\\lambdas.dat"); // processing object images; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Processing object spectra..."); Console.ForegroundColor = ConsoleColor.White; Image object_image = null; for (int i = 0; i < obj_files.Length; i++) { // Lading object image; Console.WriteLine("Loading Object image {0}", obj_files[i]); object_image = new Image(); object_image.LoadImage(obj_files[i]); if ((bool)Init.Value("TRIM_ON")) { object_image = object_image.Trim( (int)Init.Value("TRIM_STR1"), (int)Init.Value("TRIM_COL1"), (int)Init.Value("TRIM_STR2"), (int)Init.Value("TRIM_COL2")); } // Bias subtraction; Console.WriteLine("Bias subtraction..."); object_image = object_image - bias_aver; for (int j = 0; j < object_image.NAXIS1; j++) { for (int k = 0; k < object_image.NAXIS2; k++) { if (object_image[j, k] < 0) { object_image[j, k] = 0; } } } object_image.Tr(); // Cosmic rays removal; Smooth.DoSmooth(ref object_image); // Create directory for extracted spectra; string dirName = obj_files[i].Substring(0, obj_files[i].IndexOf(".fit")); int first = obj_files[i].LastIndexOf("\\"); int last = obj_files[i].IndexOf(".fit"); string fileName = dirName + "\\" + obj_files[i].Substring(first, last - first); Directory.CreateDirectory(dirName); Console.WriteLine("Extraction spectra from {0} ", obj_files[i].Substring(first)); if (bkg_mode == 0) { bkg_sw = (int)Init.Value("BKG_SW"); Extractor.ExtractMode1(object_image, pos_ord, pos_min, aperture_wing, bkg_sw); } if (bkg_mode == 1) { Image bkg_im = Background.Fit(flat_aver_db, pos_min, bkg_ox, bkg_oo, bkg_sw, bkg_step); Extractor.ExtractMode2(object_image, bkg_im, pos_ord, pos_min, aperture_wing); } fluxes = Extractor.FluxDebiased; //double[][] backgr = Extractor.Background; //Saver.SaveOrderedDistribution(backgr, fileName + "_bkg.dat"); //Saver.SaveOrderedDistribution(fluxes, fileName + "_x.dat"); for (int k = 0; k < fluxes.Length; k++) { for (int j = 0; j < fluxes[0].Length; j++) { fluxes[k][j] = fluxes[k][j] / Normator.OrdersNorm[k][j]; } } Saver.SaveLambdaIntensTable(lambdas, fluxes, dirName + "\\" + "spectra_all.dat"); for (int k = 0; k < fluxes.Length; k++) { StreamWriter sw = new StreamWriter(fileName + string.Format("_{0:000}", k) + ".dat"); for (int j = 0; j < fluxes[k].Length; j++) { sw.WriteLine( string.Format("{0:0000.0000}\t{1:0.00000E000}", lambdas[k][j], fluxes[k][j]).Replace(",", ".")); } sw.Close(); } } //output.Close(); STOP: Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("End of the pipeline. Press any key to exit..."); Console.Beep(); Console.ReadKey(); }
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; } } }