/******************************************************** * ██████╗ ██████╗████████╗██╗ * ██╔════╝ ██╔════╝╚══██╔══╝██║ * ██║ ███╗██║ ██║ ██║ * ██║ ██║██║ ██║ ██║ * ╚██████╔╝╚██████╗ ██║ ███████╗ * ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ * Geophysical Computational Tools & Library (GCTL) * * Copyright (c) 2022 Yi Zhang (yizhang-geo@zju.edu.cn) * * GCTL is distributed under a dual licensing scheme. You can redistribute * it and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either version 2 * of the License, or (at your option) any later version. You should have * received a copy of the GNU Lesser General Public License along with this * program. If not, see . * * If the terms and conditions of the LGPL v.2. would prevent you from using * the GCTL, please consider the option to obtain a commercial license for a * fee. These licenses are offered by the GCTL's original author. As a rule, * licenses are provided "as-is", unlimited in time for a one time fee. Please * send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget * to include some description of your company and the realm of its activities. * Also add information on how to contact you by electronic and paper mail. ******************************************************/ #include "gctl/core.h" #include "gctl/io.h" #include "gctl/utility.h" int main(int argc, char *argv[]) try { std::string v_str = "Treate all input columns as grid values. Set exact specification of incoming column value table(s). \ Append two chars that indicate file organization: (1) If data is in row format, state if first row is at T(op) or B(ottom). \ Then, append L or R to indicate starting point in row. (2) If data is in column format, state if first columns is \ L(left) or R(ight). Then, append T or B to indicate starting point in column."; gctl::flags_parser fp; fp.set_proname("xyz2nc"); fp.set_proinfo("Read xyz data table and write the Netcdf .nc grid files. \ This program is a toolkit of the GCTL package. The GCTL comes with ABSOLUTE NO WARRANTY. \ Please see instructions or contact the author for more information."); fp.add_opt('t', "table", required_argument, NULL, "Input data table.", "", true); fp.add_opt('r', "range", required_argument, NULL, "Range of the output grid.", "///", true); fp.add_opt('i', "interval", required_argument, NULL, "Intervals of output grid", "/", false); fp.add_opt('s', "size", required_argument, NULL, "Size of the output grid.", "/", false); fp.add_opt('g', "grid", required_argument, NULL, "Output grid file. The input table name will be used if not set.", "", false); fp.add_opt('c', "column", required_argument, NULL, "Column index of x, y and data. The defaults are 0,1,2. Append extra columns to save multiple grids in one file.", ",,,...", false); fp.add_opt('v', "value-only", required_argument, NULL, v_str.c_str(), "T|B|L|R", false); fp.add_opt('l', "label", required_argument, NULL, "Labels of x, y and data. The defaults are 'x', 'y' and 'z'.", ",,,...", false); fp.add_opt('e', "head-record", required_argument, NULL, "Input file has [0] Header record(s).", "", false); fp.add_opt('a', "annotate", required_argument, NULL, "The starting symbol of an annotate line. The default is '#'.", "", false); fp.add_opt('d', "delimeter", required_argument, NULL, "Delimeter between different columns. The default is space.", "", false); fp.add_opt('h', "help", no_argument, NULL, "Show help information.", 0, false); fp.configure(argc, argv); if (argc == 1 || fp.set_opt('h')) { fp.show_help_page(); return 0; } std::string table_name, range_str, interval_str, size_str, grid_name, col_str, label_str, head_str, ant_str, del_str, format_str; fp.get_argv({'t', 'r', 'i', 's', 'g', 'c', 'l', 'e', 'a', 'd', 'v'}, {&table_name, &range_str, &interval_str, &size_str, &grid_name, &col_str, &label_str, &head_str, &ant_str, &del_str, &format_str}); // 查看是否通过强制参数检查 if (!fp.pass_mandatory()) return 0; if (grid_name == "NULL") { size_t dpos = table_name.find_last_of('.'); if (dpos != std::string::npos) grid_name = table_name.substr(0, dpos); else grid_name = table_name; } if (col_str == "NULL") col_str = "0,1,2"; bool custom_label = false; if (label_str == "NULL") label_str = "x,y,z"; else custom_label = true; bool value_only = false; if (format_str != "NULL") value_only = true; gctl::text_descriptor desc; if (head_str != "NULL") gctl::str2type(head_str, desc.head_num_); if (ant_str != "NULL") gctl::str2type(ant_str, desc.att_sym_); if (del_str != "NULL") gctl::str2type(del_str, desc.delimiter_); if (interval_str == "NULL" && size_str == "NULL") { throw gctl::runtime_error("Either the data intervals or table sizes must be set. See the instructions for more information."); } int tmp_int, maxi_col = -1; std::string tmp_str; gctl::_1i_vector col_index; std::stringstream tmp_ss; gctl::str2ss(col_str, tmp_ss, ","); while (tmp_ss >> tmp_int) { col_index.push_back(tmp_int); maxi_col = GCTL_MAX(maxi_col, tmp_int); } gctl::_1s_vector label_index; gctl::str2ss(label_str, tmp_ss, ","); while (tmp_ss >> tmp_str) { label_index.push_back(tmp_str); } if (!value_only && col_index.size() < 3) { GCTL_ShowWhatError("Not enough column index found:", GCTL_ERROR_ERROR, col_str.c_str(), "Use -h option to see the instruction.", 0); return 0; } if (label_index.size() < 3) { GCTL_ShowWhatError("Not enough column labels found:", GCTL_ERROR_ERROR, label_str.c_str(), "Use -h option to see the instruction.", 0); return 0; } if (custom_label && col_index.size() != label_index.size()) { GCTL_ShowWhatError("Number of index and labels not match.", GCTL_ERROR_ERROR, 0, "Use -h option to see the instruction.", 0); return 0; } gctl::_2d_vector table_data; gctl::read_text2vector2d(table_name, table_data, desc); // check data for (int i = 0; i < table_data.size(); i++) { if (table_data[i].size() < maxi_col+1) { GCTL_ShowWhatError("Incomplete data set found in:", GCTL_ERROR_ERROR, table_name.c_str(), 0, 0); return 0; } } int xnum, ynum; double xmin, xmax, ymin, ymax, dx, dy; gctl::parse_string_to_value(range_str, '/', true, xmin, xmax, ymin, ymax); if (interval_str != "NULL") { gctl::parse_string_to_value(interval_str, '/', true, dx, dy); xnum = round((xmax - xmin)/dx) + 1; ynum = round((ymax - ymin)/dy) + 1; } else { gctl::parse_string_to_value(size_str, '/', true, xnum, ynum); dx = (xmax - xmin)/(xnum - 1.0); dy = (ymax - ymin)/(ynum - 1.0); } gctl::array out_data(xnum*ynum, GCTL_BDL_MAX); int tmp_M, tmp_N; if (value_only) { gctl::array val_idx(table_data.size()); if (format_str == "TL") { for (int i = 0; i < ynum; i++) { for (int j = 0; j < xnum; j++) { val_idx[j + xnum*i] = xnum*(ynum - 1 - i) + j; } } } else if (format_str == "TR") { for (int i = 0; i < ynum; i++) { for (int j = 0; j < xnum; j++) { val_idx[j + xnum*i] = xnum*(ynum - 1 - i) + xnum - 1 - j; } } } else if (format_str == "BL") { for (int i = 0; i < val_idx.size(); i++) { val_idx[i] = i; } } else if (format_str == "BR") { for (int i = 0; i < ynum; i++) { for (int j = 0; j < xnum; j++) { val_idx[j + xnum*i] = xnum*i + xnum - 1 - j; } } } else if (format_str == "LT") { for (int j = 0; j < xnum; j++) { for (int i = 0; i < ynum; i++) { val_idx[i + ynum*j] = xnum*(ynum - 1 - i) + j; } } } else if (format_str == "RT") { for (int j = 0; j < xnum; j++) { for (int i = 0; i < ynum; i++) { val_idx[i + ynum*j] = xnum*(ynum - 1 - i) + xnum - 1 - j; } } } else if (format_str == "LB") { for (int j = 0; j < xnum; j++) { for (int i = 0; i < ynum; i++) { val_idx[i + ynum*j] = xnum*i + j; } } } else if (format_str == "RB") { for (int j = 0; j < xnum; j++) { for (int i = 0; i < ynum; i++) { val_idx[i + ynum*j] = xnum*i + xnum - 1 - j; } } } for (int i = 0; i < table_data.size(); i++) { out_data[val_idx[i]] = table_data[i][col_index[0]]; } gctl::save_netcdf_grid(grid_name, out_data, xnum, ynum, xmin, dx, ymin, dy, label_index[0], label_index[1], label_index[2]); std::string save_dataname; if (col_index.size() > 1) { for (int c = 1; c < col_index.size(); c++) { out_data.assign_all(GCTL_BDL_MAX); for (int i = 0; i < table_data.size(); i++) { out_data[val_idx[i]] = table_data[i][col_index[c]]; } if (custom_label) save_dataname = label_index[c]; else save_dataname = label_index[2] + "_" + std::to_string(c-1); gctl::append_netcdf_grid(grid_name, out_data, label_index[0], label_index[1], save_dataname); } } } else { for (int i = 0; i < table_data.size(); i++) { if (table_data[i][col_index[0]] >= xmin && table_data[i][col_index[0]] <= xmax && table_data[i][col_index[1]] >= ymin && table_data[i][col_index[1]] <= ymax) { tmp_N = round((table_data[i][col_index[0]] - xmin)/dx); tmp_M = round((table_data[i][col_index[1]] - ymin)/dy); out_data[tmp_M*xnum + tmp_N] = table_data[i][col_index[2]]; } } gctl::save_netcdf_grid(grid_name, out_data, xnum, ynum, xmin, dx, ymin, dy, label_index[0], label_index[1], label_index[2]); std::string save_dataname; if (col_index.size() > 3) { for (int c = 3; c < col_index.size(); c++) { out_data.assign_all(GCTL_BDL_MAX); for (int i = 0; i < table_data.size(); i++) { if (table_data[i][col_index[0]] >= xmin && table_data[i][col_index[0]] <= xmax && table_data[i][col_index[1]] >= ymin && table_data[i][col_index[1]] <= ymax) { tmp_N = round((table_data[i][col_index[0]] - xmin)/dx); tmp_M = round((table_data[i][col_index[1]] - ymin)/dy); out_data[tmp_M*xnum + tmp_N] = table_data[i][col_index[c]]; } } if (custom_label) save_dataname = label_index[c]; else save_dataname = label_index[2] + "_" + std::to_string(c-1); gctl::append_netcdf_grid(grid_name, out_data, label_index[0], label_index[1], save_dataname); } } } return 0; } catch(std::exception &e) { GCTL_ShowWhatError(e.what(), GCTL_ERROR_ERROR, 0, 0, 0); }