""" @Project :microproduct @File :AtmosphericAuxData.PY @Function :辅助文件读写 @Author :LMM @Date :2021/09/3 14:39 @Version :1.0.0 """ import os import shutil import cftime import numpy as np import netCDF4 as Nc import math from tool.algorithm.image.ImageHandle import ImageHandler from osgeo import gdal, osr import gc import logging logger = logging.getLogger("mylog") class NcHandle: """ 气象数据的检查 气象数据的读取、降维、转tif """ def __int__(self): pass @staticmethod def check_nc(nc_infile): """ 检查气象数据 nc_infile: 气象数据路径 """ nc_data_obj = Nc.Dataset(nc_infile) keys = nc_data_obj.variables.keys() # 查看气象数据文件包含的变量列表 inform = nc_data_obj.variables variables = ['longitude', 'latitude', 'level', 'time', 'z', 'r', 't'] if len(keys) < len(variables): # 检查缺少了哪种气象数据 logger.error("下载气象数据有误,缺少参数") return False else: for var in variables: if var not in keys: logger.error("缺少气象数据:", inform[var].long_name) return False logger.info("variables check true !") all_vars_units = [] # 检查气象数据单位是否正确 for key in keys: all_vars_units.append(nc_data_obj.variables[key].units) if key == "level": if nc_data_obj.variables[key].units != "millibars": logger.error("units errors", inform[key].long_name) if key == "t": if nc_data_obj.variables[key].units != "K": logger.error("units errors", inform[key].long_name) if key == "r": if nc_data_obj.variables[key].units != "%": logger.error("units errors", inform[key].long_name) if key == "z": if nc_data_obj.variables[key].units != "m**2 s**-2": logger.error("units errors", inform[key].long_name) logger.info("The units of variables check true !") all_vars_shape = [] # 检查气象数据维数是否正确 for key in keys: all_vars_shape.append(inform[key].shape) if inform["level"].shape[0] != 37: # 检查level是否为37压力面 logger.error("shape errors", inform[key].long_name) if inform["time"].shape[0] != 1: # 检查time是否只有一个时间点 logger.error("shape errors", inform[key].long_name) if (inform["t"].shape[0]) != 1 or (inform["t"].shape[1]) != 37: logger.error("shape errors", inform[key].long_name) if inform["r"].shape[0] != 1 or inform["r"].shape[1] != 37: logger.error("shape errors", inform[key].long_name) if inform["z"].shape[0] != 1 or inform["z"].shape[1] != 37: logger.error("shape errors", inform[key].long_name) logger.info("The shape of variables check true !") @staticmethod def read_nc(nc_file): """ function: 从气象数据中读取数组 """ nc_data_obj = Nc.Dataset(nc_file) inform = nc_data_obj.variables lon_array = inform['longitude'][:] # lon数组 lat_array = inform['latitude'][:] # lat数组 n_lat = len(lat_array) # 经线列数量 n_lon = len(lon_array) # 纬线行数量 lon_min, lat_max, lon_max, lat_min = [lon_array.min(), lat_array.max(), lon_array.max(), lat_array.min()] lon_res = (lon_max - lon_min) / (float(n_lon) - 1) # 计算经度方向分辨率 lat_res = (lat_max - lat_min) / (float(n_lat) - 1) # 计算纬度方向分辨率 pre_level = np.array(inform["level"]) # pressure level in m 压力面 temp_array = np.array(inform["t"]) # temp--k (1,37,25,25) rel_hum_array = np.array(inform["r"]) # relative_humidity--% (1,37,25,25) geo_h_array = np.array(inform["z"]) # Geopotential--m**2 s**-2 (1,37,25,25) return lon_array, lat_array, pre_level, temp_array, rel_hum_array, geo_h_array, n_lat, n_lon, lon_res, lat_res def redu_dim(self, nc_file): """ function : 降低数组维度 output: lon_array: (25)-->(1,25,37) lat_array: (25)-->(1,25,37) pre_level: (37)-->(25,25,37) temp_array: (1,37,25,25)-->(25,25,37) rel_hum_array: (1,37,25,25)-->(25,25,37) geo_h_array: (1,37,25,25)-->(25,25,37) """ lon_array, lat_array, pre_level, temp_array, rel_hum_array, geo_h_array, n_lat,\ n_lon, lon_res, lat_res = self.read_nc(nc_file) lat_01 = np.zeros((1, n_lat, 37), dtype=float) lon_01 = np.zeros((1, n_lon, 37), dtype=float) level_01 = np.zeros((n_lat, n_lon, 37), dtype=float) temp_01 = np.zeros((n_lat, n_lon, 37), dtype=float) rel_hum_01 = np.zeros((n_lat, n_lon, 37), dtype=float) geo_h_01 = np.zeros((n_lat, n_lon, 37), dtype=float) for i in range(0, 37): lon_01[0, :, i] = lon_array lat_01[0, :, i] = lat_array # pre_level = pre_level/100 level_01[:, :, i] = level_01[:, :, i] + pre_level[i] temp_01[0:n_lat, 0:n_lon, i] = temp_array[0, i, :, :] rel_hum_01[0:n_lat, 0:n_lon, i] = rel_hum_array[0, i, :, :] geo_h_01[:, :, i] = geo_h_array[0, i, :, :] del lon_array, lat_array, pre_level, temp_array, rel_hum_array, geo_h_array lon_array, lat_array, pre_level, temp_array, rel_hum_array, geo_h_array =\ lon_01, lat_01, level_01, temp_01, rel_hum_01, geo_h_01 return lon_array, lat_array, pre_level, temp_array, rel_hum_array, geo_h_array, lon_res, lat_res def tran_tif(self, nc_file, out_path, str_name): """ function: 气象数据矩阵转成tiff数据 param: nc_infile 气象数据文件 param: out_path 输出的文件夹路径 param: str 气象数据名字 """ lon_array, lat_array, pre_level, temp_array, rel_hum_array, geo_h_array,\ lon_res, lat_res = self.redu_dim(nc_file) # im_bands, n_lat, n_lon = temp_array.shape dst_srs = osr.SpatialReference() dst_srs.ImportFromEPSG(4326) # 定义一个WGS84坐标系 im_proj = dst_srs.ExportToWkt() im_geo = [lon_array[0, 0, 0], lon_res, 0, lat_array[0, 0, 0], 0, -lat_res] # first_name = (nc_file.split("\\", -1)[-1]).split(".nc")[0] # out_level_path = out_path+str_name+"_"+"level.tif" # ImageHandler.write_era_into_img(out_level_path, im_proj, im_geo, pre_level) out_temp_path = out_path+str_name+"_"+"temp.tif" ImageHandler.write_era_into_img(out_temp_path, im_proj, im_geo, temp_array) out_hum_path = out_path+str_name+"_"+"re_hum.tif" ImageHandler.write_era_into_img(out_hum_path, im_proj, im_geo, rel_hum_array) out_geo_h_path = out_path+str_name+"_"+"geo_h.tif" ImageHandler.write_era_into_img(out_geo_h_path, im_proj, im_geo, geo_h_array) def copy_tif(self, nc_tif_file, out_path, key_name): """ tif格式的气象数据:1.识别文件夹中的气象参数;2.复制气象参数至临时文件夹 param: nc_tif_file:存放气象数据的文件夹路径 param: out_path:气象数据的复制路径 param: key_name:MasterNC/AuxiliaryNC """ filename = os.listdir(nc_tif_file) for name in filename: if "geo" in name: geo_path = os.path.join(nc_tif_file, name) out_path1 = os.path.join(out_path, key_name+"_geo_h.tif") shutil.copy(geo_path, out_path1) elif "hum" in name: hum_path = os.path.join(nc_tif_file, name) out_path2 = os.path.join(out_path, key_name+"_re_hum.tif") shutil.copy(hum_path, out_path2) elif "temp" in name: temp_path = os.path.join(nc_tif_file, name) out_path3 = os.path.join(out_path, key_name+"_temp.tif") shutil.copy(temp_path, out_path3) class ReadImage: """ 读取dem影像, 并输出dem矩阵 读取主辅影像,并计算干涉相位图 """ def __int__(self): pass @staticmethod def read_dem(filename): """ function: 从input目录下读取dem,返回DEM对应的数值数组 param: fileName-- dem文件路径 """ dem = ImageHandler().get_band_array(filename, 1) # dem = np.array(Image.open(filename)) max_dem = math.ceil(np.max(dem) / 100) * 100 + 50 # 四舍五入向上取值 return dem, max_dem @staticmethod def read_lon_lat(filename): """ 读取影像的经度,纬度 """ lon = [] lat = [] im_scope = ImageHandler().get_scope(filename) width, height = ImageHandler().get_img_width(filename), ImageHandler().get_img_height(filename) # 获取数据的宽度、高度 point_upleft, point_downleft = im_scope[1], im_scope[3] # 获取左上数据的[经度、纬度],右下数据的[经度、纬度] geotran = ImageHandler().get_geotransform(filename) pix_width, pix_hight = geotran[1], geotran[5] # 像元的宽度,像元的高度 # 获取像元的宽度和像元的高度 for i in range(0, width): longitude = point_upleft[0] + i * pix_width lon.append(longitude) for j in range(0, height): latitude = point_upleft[1] + j * pix_hight lat.append(latitude) lon = np.asarray(lon) lat = np.asarray(lat) lon_min, lat_max, lon_max, lat_min = [lon.min(), lat.max(), lon.max(), lat.min()] n_lat = len(lat) # 经线列数量 n_lon = len(lon) # 纬线行数量 nncols = n_lat-1 nnrows = n_lon-1 lat_37 = np.zeros((1, n_lat, 37), dtype=float) lon_37 = np.zeros((1, n_lon, 37), dtype=float) for i in range(0, 37): d = lon lon_37[0, :, i] = d e = lat lat_37[0, :, i] = e return lon, lat, lon_min, lat_max, lon_max, lat_min, n_lat, n_lon,\ nncols, nnrows, pix_width, pix_hight, lat_37, lon_37 @staticmethod def read_phase(file1, file2, out_path): """ function: 计算干涉相位 """ f01_dataset = gdal.Open(file1) # 获取主影像波段 f01_width = f01_dataset.RasterXSize f01_height = f01_dataset.RasterYSize f01_bands = f01_dataset.RasterCount img_pro = f01_dataset.GetProjection() img_tra = f01_dataset.GetGeoTransform() f01_bands1 = f01_dataset.GetRasterBand(1) f01_bands2 = f01_dataset.GetRasterBand(2) m_r_1 = f01_bands1.ReadAsArray(0, 0, f01_width, f01_height) m_i_1 = f01_bands2.ReadAsArray(0, 0, f01_width, f01_height) f02_dataset = gdal.Open(file2) # 获取辅影像波段 f02_width = f02_dataset.RasterXSize f02_height = f02_dataset.RasterYSize f02_bands = f02_dataset.RasterCount f02_bands1 = f02_dataset.GetRasterBand(1) f02_bands2 = f02_dataset.GetRasterBand(2) a_r_1 = f02_bands1.ReadAsArray(0, 0, f02_width, f02_height) a_i_1 = f02_bands2.ReadAsArray(0, 0, f02_width, f02_height) real_int_ms = m_r_1 * a_r_1 + m_i_1 * a_i_1 imag_int_ms = m_i_1 * a_r_1 - m_r_1 * a_i_1 a = real_int_ms b = imag_int_ms fan1 = np.where(a <= 0) a = np.where(a == 0, -9999, a) phase1 = np.arctan(b / a) phase1[fan1] = 0 del fan1 gc.collect() fan2 = np.where(a == 0, 1, 0) fan3 = np.where(b > 0, 1, 0) phase2 = fan2 * fan3 * math.pi / 2 del fan2, fan3 gc.collect() fan4 = np.where(a == 0, 1, 0) fan5 = np.where(b < 0, 1, 0) phase3 = fan4 * fan5 * (-math.pi / 2) del fan4, fan5 gc.collect() fan6 = np.where(a < 0, 1, 0) fan7 = np.where(b >= 0, 1, 0) a = np.where(a == 0, -9999, a) phase4 = fan6 * fan7 * (np.arctan(b / a) + math.pi) del fan6, fan7 gc.collect() fan8 = np.where(a < 0, 1, 0) fan9 = np.where(b < 0, 1, 0) a = np.where(a == 0, -9999, a) phase5 = fan8 * fan9 * (np.arctan(b / a) - math.pi) del fan8, fan9 gc.collect() phase = phase1 + phase2 + phase3 + phase4 + phase5 logger.info("Calculate phase complete !") ImageHandler.write_era_into_img(out_path, img_pro, img_tra, phase)