Manual-Labeling-Tool/Manual-Labeling-Client/WindDataOperator/Wind2ERANc.cpp

306 lines
13 KiB
C++
Raw Normal View History

2025-11-20 09:32:46 +00:00
#include "Wind2ERANc.h"
#include "WindDataFileOperator.h"
DataFileInfo get_data_file_info(const std::string& filepath) {
DataFileInfo info;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫʵ<D2AA>ִӶ<D6B4><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>ȡͷ<C8A1><CDB7>Ϣ<EFBFBD><CFA2><EFBFBD>߼<EFBFBD>
std::ifstream file(filepath, std::ios::binary);
if (file) {
file.read(reinterpret_cast<char*>(&info), sizeof(DataFileInfo));
file.close();
}
return info;
}
std::vector<int64_t> get_wind_data_file_time_arr(const std::string& filepath, const DataFileInfo& info) {
std::vector<int64_t> time_arr(info.Num);
if (get_WindDataFileTimeArr(filepath.c_str(), info, time_arr.data()) == 0) {
return time_arr;
}
else {
std::vector<int64_t> time_arra(0);
return time_arra;
}
}
bool read_wind_data_file(const std::string& filepath, const DataFileInfo& info,
int64_t time_id, std::vector<double>& u_arr, std::vector<double>& v_arr) {
if (Read_WindDataFile(filepath.c_str(),
info,
time_id, u_arr.data(), v_arr.data()) == 0) {
return true;
}
return false;
}
// <20><><EFBFBD><EFBFBD>NetCDF<44><46><EFBFBD><EFBFBD>
void ERA5NetCDFConverter::handle_netcdf_error(int status, const std::string& operation) {
if (status != NC_NOERR) {
std::cerr << "NetCDF<EFBFBD><EFBFBD><EFBFBD><EFBFBD> " << operation << ": " << nc_strerror(status) << std::endl;
throw std::runtime_error("NetCDF<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>");
}
}
// <20><>Unixʱ<78><CAB1><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>ΪERA5ʹ<35>õ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ʽ
std::vector<double> ERA5NetCDFConverter::convert_to_era5_time(const std::vector<int64_t>& unix_timestamps) {
std::vector<double> era5_times;
era5_times.reserve(unix_timestamps.size());
// ERA5ʱ<35><CAB1>ͨ<EFBFBD><CDA8><EFBFBD>Ǵ<EFBFBD>1900-01-01<30><31>ʼ<EFBFBD><CABC>Сʱ<D0A1><CAB1>
const auto era5_epoch = std::chrono::system_clock::from_time_t(-2208988800); // 1900-01-01
for (auto timestamp : unix_timestamps) {
auto time_point = std::chrono::system_clock::from_time_t(timestamp);
auto duration = std::chrono::duration_cast<std::chrono::hours>(time_point - era5_epoch);
era5_times.push_back(static_cast<double>(duration.count()));
}
return era5_times;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>γ<EFBFBD><CEB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<double> ERA5NetCDFConverter::create_coordinate_array(double min, double max, size_t size) {
std::vector<double> coord(size);
double step = (max - min) / (size - 1);
for (size_t i = 0; i < size; ++i) {
coord[i] = min + i * step;
}
return coord;
}
bool ERA5NetCDFConverter::convert_to_era5_netcdf(const std::string& input_bin_file, const std::string& output_nc_file) {
try {
// 1. <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>Ϣ
DataFileInfo info = getDataFileInfo(input_bin_file.c_str());
std::cout << "<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>Ϣ: " << info.Height << "x" << info.Width
<< " <20><><EFBFBD><EFBFBD>, " << info.Num << " <20><>ʱ<EFBFBD>" << std::endl;
// 2. <20><>ȡʱ<C8A1><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<int64_t> time_arr = get_wind_data_file_time_arr(input_bin_file.c_str(), info);
if (time_arr.empty()) {
std::cerr << "<EFBFBD>޷<EFBFBD><EFBFBD><EFBFBD>ȡʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" << std::endl;
return false;
}
// 3. <20><><EFBFBD><EFBFBD>NetCDF<44>ļ<EFBFBD>
int ncid, status;
status = nc_create(output_nc_file.c_str(), NC_NETCDF4, &ncid);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>");
// 4. <20><><EFBFBD><EFBFBD>ά<EFBFBD><CEAC>
int lon_dim, lat_dim, time_dim;
status = nc_def_dim(ncid, "longitude", info.Width, &lon_dim);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD>");
status = nc_def_dim(ncid, "latitude", info.Height, &lat_dim);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>γ<EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD>");
status = nc_def_dim(ncid, "time", NC_UNLIMITED, &time_dim);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD>");
// 5. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int lon_var, lat_var, time_var;
int dims_coord[1] = { lon_dim };
status = nc_def_var(ncid, "longitude", NC_DOUBLE, 1, dims_coord, &lon_var);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><EFBFBD><EFBFBD>");
dims_coord[0] = lat_dim;
status = nc_def_var(ncid, "latitude", NC_DOUBLE, 1, dims_coord, &lat_var);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>γ<EFBFBD>ȱ<EFBFBD><EFBFBD><EFBFBD>");
dims_coord[0] = time_dim;
status = nc_def_var(ncid, "time", NC_DOUBLE, 1, dims_coord, &time_var);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
// 6. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><DDB1><EFBFBD><EFBFBD><EFBFBD>U<EFBFBD><55>V<EFBFBD><56><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int u10_var, v10_var;
int dims_data[3] = { time_dim, lat_dim, lon_dim };
status = nc_def_var(ncid, "u10", NC_DOUBLE, 3, dims_data, &u10_var);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>u10<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
status = nc_def_var(ncid, "v10", NC_DOUBLE, 3, dims_data, &v10_var);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>v10<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
// 7. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::string time_units = "hours since 1900-01-01 00:00:00.0";
status = nc_put_att_text(ncid, time_var, "units", time_units.length(), time_units.c_str());
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>䵥λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
status = nc_put_att_text(ncid, lon_var, "units", 12, "degrees_east");
status = nc_put_att_text(ncid, lat_var, "units", 13, "degrees_north");
status = nc_put_att_text(ncid, u10_var, "units", 6, "m s**-1");
status = nc_put_att_text(ncid, v10_var, "units", 6, "m s**-1");
status = nc_put_att_text(ncid, u10_var, "long_name", 25, "10 metre U wind component");
status = nc_put_att_text(ncid, v10_var, "long_name", 25, "10 metre V wind component");
// 8. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
status = nc_enddef(ncid);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ");
// 9. д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<double> lon_data = create_coordinate_array(info.minLon, info.maxLon, info.Width);
std::vector<double> lat_data = create_coordinate_array(info.minLat, info.maxLat, info.Height);
std::reverse(lat_data.begin(), lat_data.end());
std::vector<double> era5_time = convert_to_era5_time(time_arr);
status = nc_put_var_double(ncid, lon_var, lon_data.data());
handle_netcdf_error(status, "д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
status = nc_put_var_double(ncid, lat_var, lat_data.data());
handle_netcdf_error(status, "д<EFBFBD><EFBFBD>γ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
status = nc_put_var_double(ncid, time_var, era5_time.data());
handle_netcdf_error(status, "д<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
// 10. д<><D0B4><EFBFBD><EFBFBD><E7B3A1><EFBFBD><EFBFBD>
std::vector<double> u_data(info.Height * info.Width);
std::vector<double> v_data(info.Height * info.Width);
size_t start[3] = { 0, 0, 0 };
size_t count[3] = { 1, info.Height, info.Width };
for (int64_t t = 0; t < info.Num; ++t) {
if (read_wind_data_file(input_bin_file, info, t, u_data, v_data)) {
start[0] = t;
status = nc_put_vara_double(ncid, u10_var, start, count, u_data.data());
handle_netcdf_error(status, "д<EFBFBD><EFBFBD>u10<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
status = nc_put_vara_double(ncid, v10_var, start, count, v_data.data());
handle_netcdf_error(status, "д<EFBFBD><EFBFBD>v10<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
if (t % 10 == 0) {
std::cout << "<EFBFBD>Ѵ<EFBFBD><EFBFBD><EFBFBD> " << t + 1 << "/" << info.Num << " <20><>ʱ<EFBFBD>" << std::endl;
}
}
}
// 11. <20>ر<EFBFBD><D8B1>ļ<EFBFBD>
status = nc_close(ncid);
handle_netcdf_error(status, "<EFBFBD>ر<EFBFBD><EFBFBD>ļ<EFBFBD>");
std::cout << "ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>: " << output_nc_file << std::endl;
return true;
}
catch (const std::exception& e) {
std::cerr << "ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̳<EFBFBD><EFBFBD><EFBFBD>: " << e.what() << std::endl;
return false;
}
}
bool ERA5NetCDFConverter::convert_to_era5_netcdf(const std::string& input_bin_file, const std::string& output_nc_file, int64_t tid)
{
try {
// 1. <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>Ϣ
DataFileInfo info = getDataFileInfo(input_bin_file.c_str());
std::cout << "<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>Ϣ: " << info.Height << "x" << info.Width
<< " <20><><EFBFBD><EFBFBD>, " << info.Num << " <20><>ʱ<EFBFBD>" << std::endl;
// 2. <20><>ȡʱ<C8A1><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<int64_t> time_arr = get_wind_data_file_time_arr(input_bin_file.c_str(), info);
if (time_arr.empty()) {
std::cerr << "<EFBFBD>޷<EFBFBD><EFBFBD><EFBFBD>ȡʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" << std::endl;
return false;
}
// 3. <20><><EFBFBD><EFBFBD>NetCDF<44>ļ<EFBFBD>
int ncid, status;
status = nc_create(output_nc_file.c_str(), NC_NETCDF4, &ncid);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>");
// 4. <20><><EFBFBD><EFBFBD>ά<EFBFBD><CEAC>
int lon_dim, lat_dim, time_dim;
status = nc_def_dim(ncid, "longitude", info.Width, &lon_dim);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD>");
status = nc_def_dim(ncid, "latitude", info.Height, &lat_dim);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>γ<EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD>");
status = nc_def_dim(ncid, "time", NC_UNLIMITED, &time_dim);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD>");
// 5. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int lon_var, lat_var, time_var;
int dims_coord[1] = { lon_dim };
status = nc_def_var(ncid, "longitude", NC_DOUBLE, 1, dims_coord, &lon_var);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><EFBFBD><EFBFBD>");
dims_coord[0] = lat_dim;
status = nc_def_var(ncid, "latitude", NC_DOUBLE, 1, dims_coord, &lat_var);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>γ<EFBFBD>ȱ<EFBFBD><EFBFBD><EFBFBD>");
dims_coord[0] = time_dim;
status = nc_def_var(ncid, "time", NC_DOUBLE, 1, dims_coord, &time_var);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
// 6. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><DDB1><EFBFBD><EFBFBD><EFBFBD>U<EFBFBD><55>V<EFBFBD><56><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int u10_var, v10_var;
int dims_data[3] = { time_dim, lat_dim, lon_dim };
status = nc_def_var(ncid, "u10", NC_DOUBLE, 3, dims_data, &u10_var);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>u10<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
status = nc_def_var(ncid, "v10", NC_DOUBLE, 3, dims_data, &v10_var);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>v10<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
// 7. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::string time_units = "hours since 1900-01-01 00:00:00.0";
status = nc_put_att_text(ncid, time_var, "units", time_units.length(), time_units.c_str());
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>䵥λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
status = nc_put_att_text(ncid, lon_var, "units", 12, "degrees_east");
status = nc_put_att_text(ncid, lat_var, "units", 13, "degrees_north");
status = nc_put_att_text(ncid, u10_var, "units", 6, "m s**-1");
status = nc_put_att_text(ncid, v10_var, "units", 6, "m s**-1");
status = nc_put_att_text(ncid, u10_var, "long_name", 25, "10 metre U wind component");
status = nc_put_att_text(ncid, v10_var, "long_name", 25, "10 metre V wind component");
// 8. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
status = nc_enddef(ncid);
handle_netcdf_error(status, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ");
// 9. д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<double> lon_data = create_coordinate_array(info.minLon, info.maxLon, info.Width);
std::vector<double> lat_data = create_coordinate_array(info.minLat, info.maxLat, info.Height);
std::vector<double> era5_time = convert_to_era5_time(time_arr);
std::reverse(lat_data.begin(), lat_data.end());
status = nc_put_var_double(ncid, lon_var, lon_data.data());
handle_netcdf_error(status, "д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
status = nc_put_var_double(ncid, lat_var, lat_data.data());
handle_netcdf_error(status, "д<EFBFBD><EFBFBD>γ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
status = nc_put_var_double(ncid, time_var, era5_time.data());
handle_netcdf_error(status, "д<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
// 10. д<><D0B4><EFBFBD><EFBFBD><E7B3A1><EFBFBD><EFBFBD>
std::vector<double> u_data(info.Height * info.Width);
std::vector<double> v_data(info.Height * info.Width);
size_t start[3] = { 0, 0, 0 };
size_t count[3] = { 1, info.Height, info.Width };
for (int64_t t = 0; t < info.Num; ++t) {
if (t != tid) { continue; }
if (read_wind_data_file(input_bin_file, info, t, u_data, v_data)) {
start[0] = t;
status = nc_put_vara_double(ncid, u10_var, start, count, u_data.data());
handle_netcdf_error(status, "д<EFBFBD><EFBFBD>u10<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
status = nc_put_vara_double(ncid, v10_var, start, count, v_data.data());
handle_netcdf_error(status, "д<EFBFBD><EFBFBD>v10<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
if (t % 10 == 0) {
std::cout << "<EFBFBD>Ѵ<EFBFBD><EFBFBD><EFBFBD> " << t + 1 << "/" << info.Num << " <20><>ʱ<EFBFBD>" << std::endl;
}
}
}
// 11. <20>ر<EFBFBD><D8B1>ļ<EFBFBD>
status = nc_close(ncid);
handle_netcdf_error(status, "<EFBFBD>ر<EFBFBD><EFBFBD>ļ<EFBFBD>");
std::cout << "ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>: " << output_nc_file << std::endl;
return true;
}
catch (const std::exception& e) {
std::cerr << "ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̳<EFBFBD><EFBFBD><EFBFBD>: " << e.what() << std::endl;
return false;
}
}