def main(ifile, shp_file, path_out_10m, path_out_20m, path_out_60m, aero_type=1, target_type=2, altitude=0.01, visibility=15): if os.path.isfile(ifile): print('文件解压...') fz = zipfile.ZipFile(ifile, 'r') for file in fz.namelist(): fz.extract(file, os.path.split(ifile)[0]) path_name = os.path.split(fz.namelist()[0])[0] path_in = os.path.join(os.path.split(ifile)[0], path_name) else: path_in = ifile # 卫星经纬度范围 path_xml = os.listdir(os.path.join(path_in, 'GRANULE'))[0] file_mtd = os.path.join(path_in, 'GRANULE', path_xml, 'MTD_TL.xml') with open(file_mtd, 'r') as fp: for line in fp: res = re.findall(r'psd-\d+', line) if len(res) != 0: psd_str = '{https://%s.sentinel2.eo.esa.int/PSD/S2_PDI_Level-1C_Tile_Metadata.xsd}Geometric_Info' % res[ 0] break tree = ET.parse(file_mtd) ulx = parse_xml(tree, [[psd_str, None], ['Tile_Geocoding', None], ['Geoposition', None], ['ULX', None]]) ulx = int(ulx) uly = parse_xml(tree, [[psd_str, None], ['Tile_Geocoding', None], ['Geoposition', None], ['ULY', None]]) uly = int(uly) # EPSG代码 epsg = parse_xml(tree, [[psd_str, None], ['Tile_Geocoding', None], ['HORIZONTAL_CS_CODE', None]]) epsg = re.findall(r'\d+', epsg) epsg = int(epsg[0]) # 60m分辨率的行列数 nrows = parse_xml(tree, [[psd_str, None], ['Tile_Geocoding', None], ['Size', { 'resolution': '60' }], ['NROWS', None]]) nrows = int(nrows) ncols = parse_xml(tree, [[psd_str, None], ['Tile_Geocoding', None], ['Size', { 'resolution': '60' }], ['NCOLS', None]]) ncols = int(ncols) # 计算裁切范围-10m if shp_file: tif_tmp = 'tif_tmp.tif' else: tif_tmp = shp_file.replace('.shp', '_tmp.tif') target_ds = gdal.GetDriverByName('GTiff').Create(tif_tmp, ncols * 6, nrows * 6, 1, gdal.GDT_Byte) geo_trans = (ulx, 10, 0, uly, 0, -10) raster_srs = osr.SpatialReference() raster_srs.ImportFromEPSG(epsg) proj_ref = raster_srs.ExportToWkt() target_ds.SetGeoTransform(geo_trans) target_ds.SetProjection(proj_ref) data_tmp = np.zeros([nrows, ncols]).astype(np.uint8) target_ds.GetRasterBand(1).WriteArray(data_tmp) target_ds = None if shp_file: out_file = 'tif_mask.tif' else: out_file = shp_file.replace('.shp', '_mask.tif') cut_range_10m = img_cut.main(tif_tmp, shp_file=shp_file, out_file=out_file) os.remove(out_file) os.remove(tif_tmp) # 计算裁切范围-20m target_ds = gdal.GetDriverByName('GTiff').Create(tif_tmp, ncols * 3, nrows * 3, 1, gdal.GDT_Byte) geo_trans = (ulx, 20, 0, uly, 0, -20) raster_srs = osr.SpatialReference() raster_srs.ImportFromEPSG(epsg) proj_ref = raster_srs.ExportToWkt() target_ds.SetGeoTransform(geo_trans) target_ds.SetProjection(proj_ref) data_tmp = np.zeros([nrows, ncols]).astype(np.uint8) target_ds.GetRasterBand(1).WriteArray(data_tmp) target_ds = None cut_range_20m = img_cut.main(tif_tmp, shp_file=shp_file, out_file=out_file) os.remove(out_file) os.remove(tif_tmp) # 计算裁切范围-60m target_ds = gdal.GetDriverByName('GTiff').Create(tif_tmp, ncols, nrows, 1, gdal.GDT_Byte) geo_trans = (ulx, 60, 0, uly, 0, -60) raster_srs = osr.SpatialReference() raster_srs.ImportFromEPSG(epsg) proj_ref = raster_srs.ExportToWkt() target_ds.SetGeoTransform(geo_trans) target_ds.SetProjection(proj_ref) data_tmp = np.zeros([nrows, ncols]).astype(np.uint8) target_ds.GetRasterBand(1).WriteArray(data_tmp) target_ds = None cut_range_60m = img_cut.main(tif_tmp, shp_file=shp_file, out_file=out_file) os.remove(out_file) os.remove(tif_tmp) # 观测天顶角和方位角 salz = parse_xml( tree, [[psd_str, None], ['Tile_Angles', None], ['Mean_Viewing_Incidence_Angle_List', None], ['Mean_Viewing_Incidence_Angle', None], ['ZENITH_ANGLE', None]]) sala = parse_xml( tree, [[psd_str, None], ['Tile_Angles', None], ['Mean_Viewing_Incidence_Angle_List', None], ['Mean_Viewing_Incidence_Angle', None], ['AZIMUTH_ANGLE', None]]) # 太阳天顶角和方位角 path_in_short = os.path.split(path_in)[1] date_str = path_in_short.split('_')[2] year = int(date_str[0:4]) month = int(date_str[4:6]) day = int(date_str[6:8]) hour = int(date_str[9:11]) minute = int(date_str[11:13]) second = int(date_str[13:15]) date = '%d/%d/%d %d:%d:%d' % (year, month, day, hour, minute, second) center_lonlat = coord_trans.trans(epsg, 4326, ulx + (ncols / 2) * 60, uly - (nrows / 2) * 60) [solz, sola] = calc_sola_position.main(center_lonlat[0], center_lonlat[1], date) path_data = os.path.join(path_in, 'GRANULE', path_xml, 'IMG_DATA') data_list = os.listdir(path_data) # 首次循环:识别波段 for item in data_list: if 'B01' in item: name_b1 = item break name_10m = [ name_b1.replace('B01', 'B02'), name_b1.replace('B01', 'B03'), name_b1.replace('B01', 'B04'), name_b1.replace('B01', 'B08') ] name_20m = [ name_b1.replace('B01', 'B02'), name_b1.replace('B01', 'B03'), name_b1.replace('B01', 'B04'), name_b1.replace('B01', 'B05'), name_b1.replace('B01', 'B06'), name_b1.replace('B01', 'B07'), name_b1.replace('B01', 'B08'), name_b1.replace('B01', 'B8A'), name_b1.replace('B01', 'B11'), name_b1.replace('B01', 'B12') ] name_60m = [ name_b1, name_b1.replace('B01', 'B02'), name_b1.replace('B01', 'B03'), name_b1.replace('B01', 'B04'), name_b1.replace('B01', 'B05'), name_b1.replace('B01', 'B06'), name_b1.replace('B01', 'B07'), name_b1.replace('B01', 'B08'), name_b1.replace('B01', 'B8A'), name_b1.replace('B01', 'B09'), name_b1.replace('B01', 'B10'), name_b1.replace('B01', 'B11'), name_b1.replace('B01', 'B12') ] # 10m波段 print('10m ...') file_out_short = os.path.split(path_in)[1] file_out_split = file_out_short.split('_') date_str = file_out_split[2].replace('T', '') date_str = str(int(date_str) + 80000) # 转换为北京时间 nrow = file_out_split[3].replace('N', '') npath = file_out_split[4].replace('R', '') if file_out_split[0] == 'S2A': satellite_code = 'A' elif file_out_split[0] == 'S2B': satellite_code = 'B' else: satellite_code = '' name_short = 'Sentinel2%s_MSI_10_L2_%s_%s_%s.tif' % (satellite_code, date_str, nrow, npath) file_out = os.path.join(path_out_10m, name_short) nbands = len(name_10m) xsize = cut_range_10m[1] - cut_range_10m[0] ysize = cut_range_10m[3] - cut_range_10m[2] target_ds = gdal.GetDriverByName('GTiff').Create(file_out, xsize, ysize, nbands, gdal.GDT_Int16) geo_trans = (ulx + cut_range_10m[0] * 10, 10, 0, uly - cut_range_10m[2] * 10, 0, -10) raster_srs = osr.SpatialReference() raster_srs.ImportFromEPSG(epsg) proj_ref = raster_srs.ExportToWkt() target_ds.SetGeoTransform(geo_trans) target_ds.SetProjection(proj_ref) nband = 0 for item in name_10m: raster = gdal.Open(os.path.join(path_data, item)) data = raster.GetRasterBand(1).ReadAsArray() nan_mask = data == 0 raster = None radi_cali = data.astype(float) / 10000 # 大气校正 mtl_coef = { 'altitude': altitude, 'visibility': visibility, 'aero_type': aero_type, 'target_type': target_type, 'location': center_lonlat, 'month': month, 'day': day, 'solz': solz, 'sola': sola, 'salz': salz, 'sala': sala } wave_index = item[-7:-4] res_atms_corr = arms_corr(radi_cali, mtl_coef, wave_index) # 裁切 res_atms_corr = res_atms_corr[cut_range_10m[2]:cut_range_10m[3], cut_range_10m[0]:cut_range_10m[1]] res_atms_corr = res_atms_corr * 10000 res_atms_corr[nan_mask] = -9999 target_ds.GetRasterBand(nband + 1).WriteArray( (res_atms_corr).astype(np.int)) target_ds.GetRasterBand(nband + 1).SetNoDataValue(-9999) nband = nband + 1 print('%s处理完毕...' % wave_index) target_ds = None # 20m波段 print('20m ...') name_short_20m = name_short.replace('_10_', '_20_') file_out = os.path.join(path_out_20m, name_short_20m) nbands = len(name_20m) xsize = cut_range_20m[1] - cut_range_20m[0] ysize = cut_range_20m[3] - cut_range_20m[2] target_ds = gdal.GetDriverByName('GTiff').Create(file_out, xsize, ysize, nbands, gdal.GDT_Int16) geo_trans = (ulx + cut_range_20m[0] * 20, 20, 0, uly - cut_range_20m[2] * 20, 0, -20) raster_srs = osr.SpatialReference() raster_srs.ImportFromEPSG(epsg) proj_ref = raster_srs.ExportToWkt() target_ds.SetGeoTransform(geo_trans) target_ds.SetProjection(proj_ref) nband = 0 for item in name_20m: raster = gdal.Open(os.path.join(path_data, item)) data = raster.GetRasterBand(1).ReadAsArray() # 降采样 if item in name_10m: data_resample = np.zeros( [int(data.shape[0] / 2), int(data.shape[1] / 2)]) for i in range(2): for j in range(2): data_resample = data_resample + data[i::2, j::2] data = data_resample / 4 nan_mask = data == 0 raster = None radi_cali = data.astype(float) / 10000 # 大气校正 mtl_coef = { 'altitude': altitude, 'visibility': visibility, 'aero_type': aero_type, 'target_type': target_type, 'location': center_lonlat, 'month': month, 'day': day, 'solz': solz, 'sola': sola, 'salz': salz, 'sala': sala } wave_index = item[-7:-4] res_atms_corr = arms_corr(radi_cali, mtl_coef, wave_index) # 裁切 res_atms_corr = res_atms_corr[cut_range_20m[2]:cut_range_20m[3], cut_range_20m[0]:cut_range_20m[1]] res_atms_corr = res_atms_corr * 10000 res_atms_corr[nan_mask] = -9999 target_ds.GetRasterBand(nband + 1).WriteArray( (res_atms_corr).astype(np.int)) target_ds.GetRasterBand(nband + 1).SetNoDataValue(-9999) nband = nband + 1 print('%s处理完毕...' % wave_index) target_ds = None # 60m波段 print('60m ...') name_short_60m = name_short.replace('_10_', '_60_') file_out = os.path.join(path_out_60m, name_short_60m) nbands = len(name_60m) xsize = cut_range_60m[1] - cut_range_60m[0] ysize = cut_range_60m[3] - cut_range_60m[2] target_ds = gdal.GetDriverByName('GTiff').Create(file_out, xsize, ysize, nbands, gdal.GDT_Int16) geo_trans = (ulx + cut_range_60m[0] * 60, 60, 0, uly - cut_range_60m[2] * 60, 0, -60) raster_srs = osr.SpatialReference() raster_srs.ImportFromEPSG(epsg) proj_ref = raster_srs.ExportToWkt() target_ds.SetGeoTransform(geo_trans) target_ds.SetProjection(proj_ref) nband = 0 for item in name_60m: raster = gdal.Open(os.path.join(path_data, item)) data = raster.GetRasterBand(1).ReadAsArray() # 降采样 if item in name_10m: data_resample = np.zeros( [int(data.shape[0] / 6), int(data.shape[1] / 6)]) for i in range(6): for j in range(6): data_resample = data_resample + data[i::6, j::6] data = data_resample / 36 elif item in name_20m: data_resample = np.zeros( [int(data.shape[0] / 3), int(data.shape[1] / 3)]) for i in range(3): for j in range(3): data_resample = data_resample + data[i::3, j::3] data = data_resample / 9 nan_mask = data == 0 raster = None radi_cali = data.astype(float) / 10000 # 大气校正 mtl_coef = { 'altitude': altitude, 'visibility': visibility, 'aero_type': aero_type, 'target_type': target_type, 'location': center_lonlat, 'month': month, 'day': day, 'solz': solz, 'sola': sola, 'salz': salz, 'sala': sala } wave_index = item[-7:-4] if wave_index == 'B10': res_atms_corr = radi_cali else: res_atms_corr = arms_corr(radi_cali, mtl_coef, wave_index) # 裁切 res_atms_corr = res_atms_corr[cut_range_60m[2]:cut_range_60m[3], cut_range_60m[0]:cut_range_60m[1]] res_atms_corr = res_atms_corr * 10000 res_atms_corr[nan_mask] = -9999 target_ds.GetRasterBand(nband + 1).WriteArray( (res_atms_corr).astype(np.int)) target_ds.GetRasterBand(nband + 1).SetNoDataValue(-9999) nband = nband + 1 print('%s处理完毕...' % wave_index) target_ds = None # 删除解压文件 if os.path.isfile(ifile): shutil.rmtree(path_in)
def main(ifile, path_out_30, shp_file=None, altitude=0.01, visibility=40.0, type_aero=1): ''' @description: @ifile {str} tar.gz原始数据文件 @path_out_30 {str} 预处理后的文件输出路径 @shp_file {str} 矢量文件路径 @altitude {float} 海拔(km) @visibility {float} 能见度(km) @type_aero {int} 气溶胶类型(3默认为城市) ''' tf = tarfile.open(ifile) path_short = os.path.split(ifile)[1] path_short = path_short.replace('.tar.gz', '') file_path = os.path.join(os.path.split(ifile)[0], path_short) print('文件解压...') tf.extractall(path=file_path) file_list = os.listdir(file_path) MTLfile = '' band_list = [0, 1, 2, 3, 4, 5, 6] for item in file_list: if 'MTL.txt' in item: MTLfile = item break raster_b1 = os.path.join(file_path, MTLfile.replace('MTL.txt', 'B2.TIF')) lim = img_cut.main(raster_file = raster_b1, shp_file = shp_file) xlim = [lim[0], lim[1]] ylim = [lim[2], lim[3]] raster_data_res = np.zeros((ylim[1]-ylim[0], xlim[1]-xlim[0], len(band_list))) MTLfile = os.path.join(file_path, MTLfile) print('预处理...') for i in band_list: print('裁切...') raster_file = os.path.join(file_path, MTLfile.replace('MTL.txt', 'B'+str(i+1)+'.TIF')) raster_data = skimage.io.imread(raster_file) # 裁切 raster_data = raster_data[ylim[0]:ylim[1], xlim[0]:xlim[1]] # 辐射定标和大气校正(6S) nan_key = raster_data < 1e-6 band_data_atmscorr = radi_arms_corr(raster_data=raster_data, MTLfile=MTLfile, altitude=altitude, visibility=visibility, type_aero=type_aero, wave_index=i) band_data_atmscorr[nan_key] = 0 raster_data_res[:,:,i] = band_data_atmscorr print('第%d波段已经处理完毕' % (i+1)) # 数据保存为tif raster_file = os.path.join(file_path, MTLfile.replace('MTL.txt', 'B1.TIF')) raster = gdal.Open(raster_file) georef0 = raster.GetGeoTransform() georef1 = list(georef0) georef1[0] = georef0[0] + xlim[0] * georef0[1] georef1[3] = georef0[3] + ylim[0] * georef0[5] georef1 = tuple(georef1) # 可见光-短波红外 ifile_name = os.path.split(ifile)[1] date_str = '%s103000' % (ifile_name.split('_')[3]) nrow = ifile_name.split('_')[2][0:3] npath = ifile_name.split('_')[2][3:6] name_short = 'Landsat5_TM_30_L2_%s_%s_%s.tif' % (date_str, nrow, npath) raster_file_out = os.path.join(path_out_30, name_short) if os.path.exists(raster_file_out): # 如果文件存在则需要删除 os.remove(raster_file_out) target_ds = gdal.GetDriverByName('GTiff').Create( raster_file_out, raster_data_res.shape[1], raster_data_res.shape[0], len(band_list), gdal.GDT_UInt16 ) target_ds.SetGeoTransform(georef1) target_ds.SetProjection(raster.GetProjectionRef()) for i in band_list: print('保存第%d波段...' % (i+1)) if i != 5: data_tmp = (raster_data_res[:,:,i]*10000).astype(np.int) else: data_tmp = (raster_data_res[:,:,i]*100).astype(np.int) data_tmp[data_tmp<1e-6] = 0 target_ds.GetRasterBand(i+1).WriteArray(data_tmp) target_ds.GetRasterBand(i+1).SetNoDataValue(0) target_ds = None # 删除解压文件 raster = None shutil.rmtree(file_path)
def satellite_position(ifile, shp_file): ''' @description: 相对精确的天顶角方位角计算 @ifile {str}: L1B swath文件 @shp_file {str}: 研究区域矢量文件 @return: {salz, sala} ''' # 设置环境变量 os.environ['MRTDATADIR'] = global_config['MRTDATADIR'] os.environ['PGSHOME'] = global_config['PGSHOME'] os.environ['MRTBINDIR'] = global_config['MRTBINDIR'] run_path = os.path.split(ifile)[0] heg_bin = os.path.join(global_config['MRTBINDIR'], 'hegtool') os.system('cd %s && %s -h %s > heg.log' % (run_path, heg_bin, ifile)) info_file = os.path.join(run_path, 'HegHdr.hdr') if not(os.path.exists(info_file)): print('获取文件信息出错:%s' % ifile) return(0) else: lat_min = None lat_max = None lon_min = None lon_max = None pixel_x = None pixel_y = None with open(info_file, 'r') as fp: lines = fp.readlines() for line in lines: if 'SWATH_LAT_MIN' in line: lat_min = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_LAT_MAX' in line: lat_max = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_LON_MIN' in line: lon_min = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_LON_MAX' in line: lon_max = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_X_PIXEL_RES_DEGREES' in line: pixel_x = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_Y_PIXEL_RES_DEGREES' in line: pixel_y = float(re.findall(r'[\d.]+', line)[0]) if lat_min and lat_max and lon_min and lon_max and pixel_x and pixel_y: prm_file = os.path.join(run_path, 'HegSwath.prm') # 卫星天顶角、方位角重投影 print('reprojection SALZ ...') if '.hdf' in ifile: out_file = ifile.replace('.hdf', '_SALZ.tif') if os.path.exists(out_file): os.remove(out_file) else: print('无法识别的文件格式:%s' % os.path.split(ifile)[1]) with open(prm_file, 'wb') as fp: fp.write(b'\nNUM_RUNS = 1\n\n') fp.write(b'BEGIN\n') fp.write(bytes('INPUT_FILENAME = %s\n' % ifile, 'utf-8')) fp.write(b'OBJECT_NAME = MODIS_SWATH_Type_L1B\n') fp.write(b'FIELD_NAME = SensorZenith|\n') fp.write(b'BAND_NUMBER = 1\n') fp.write(bytes('OUTPUT_PIXEL_SIZE_X = %f\n' % pixel_x, 'utf-8')) fp.write(bytes('OUTPUT_PIXEL_SIZE_Y = %f\n' % pixel_y, 'utf-8')) fp.write(bytes('SPATIAL_SUBSET_UL_CORNER = ( %f %f )\n' % (lat_max, lon_min), 'utf-8')) fp.write(bytes('SPATIAL_SUBSET_LR_CORNER = ( %f %f )\n' % (lat_min, lon_max), 'utf-8')) fp.write(b'OUTPUT_PROJECTION_TYPE = GEO\n') fp.write(bytes('OUTPUT_FILENAME = %s\n' % out_file, 'utf-8')) fp.write(b'OUTPUT_TYPE = GEO\n') fp.write(b'END\n\n') swtif_bin = os.path.join(global_config['MRTBINDIR'], 'swtif') os.system('cd %s && %s -P HegSwath.prm > heg.log' % (run_path, swtif_bin)) print('reprojection SALA ...') if '.hdf' in ifile: out_file = ifile.replace('.hdf', '_SALA.tif') if os.path.exists(out_file): os.remove(out_file) else: print('无法识别的文件格式:%s' % os.path.split(ifile)[1]) with open(prm_file, 'wb') as fp: fp.write(b'\nNUM_RUNS = 1\n\n') fp.write(b'BEGIN\n') fp.write(bytes('INPUT_FILENAME = %s\n' % ifile, 'utf-8')) fp.write(b'OBJECT_NAME = MODIS_SWATH_Type_L1B\n') fp.write(b'FIELD_NAME = SensorAzimuth|\n') fp.write(b'BAND_NUMBER = 1\n') fp.write(bytes('OUTPUT_PIXEL_SIZE_X = %f\n' % pixel_x, 'utf-8')) fp.write(bytes('OUTPUT_PIXEL_SIZE_Y = %f\n' % pixel_y, 'utf-8')) fp.write(bytes('SPATIAL_SUBSET_UL_CORNER = ( %f %f )\n' % (lat_max, lon_min), 'utf-8')) fp.write(bytes('SPATIAL_SUBSET_LR_CORNER = ( %f %f )\n' % (lat_min, lon_max), 'utf-8')) fp.write(b'OUTPUT_PROJECTION_TYPE = GEO\n') fp.write(bytes('OUTPUT_FILENAME = %s\n' % out_file, 'utf-8')) fp.write(b'OUTPUT_TYPE = GEO\n') fp.write(b'END\n\n') swtif_bin = os.path.join(global_config['MRTBINDIR'], 'swtif') os.system('cd %s && %s -P HegSwath.prm > heg.log' % (run_path, swtif_bin)) else: print('[Error] 未获得全部的所需信息') return(0) # 计算研究区域的平均太阳天顶角和方位角 salz_file = ifile.replace('.hdf', '_SALZ.tif') out_file = salz_file.replace('.tif', '_cut.tif') cut_range = img_cut.main(salz_file, shp_file=shp_file, out_file=out_file) raster = gdal.Open(salz_file) salz_all = raster.GetRasterBand(1).ReadAsArray() salz_all = salz_all[cut_range[2]:cut_range[3], cut_range[0]:cut_range[1]] salz = np.mean(salz_all) * 0.01 sala_file = ifile.replace('.hdf', '_SALA.tif') raster = gdal.Open(sala_file) sala_all = raster.GetRasterBand(1).ReadAsArray() sala_all = sala_all[cut_range[2]:cut_range[3], cut_range[0]:cut_range[1]] sala = np.mean(sala_all) * 0.01 raster = None # 删除过程文件 file_name = ifile.replace('.hdf', '_SALA.tif') file_name_met = file_name.replace('.tif', '.tif.met') if os.path.exists(file_name) and os.path.exists(file_name_met): os.remove(file_name) os.remove(file_name_met) file_name = ifile.replace('.hdf', '_SALZ.tif') file_name_met = file_name.replace('.tif', '.tif.met') if os.path.exists(file_name) and os.path.exists(file_name_met): os.remove(file_name) os.remove(file_name_met) file_name = ifile.replace('.hdf', '_SALZ_cut.tif') if os.path.exists(file_name): os.remove(file_name) log_list = ['heg.log', 'swtif.log', 'HegSwath.prm', 'HegHdr.hdr', 'hegtool.log'] for item in log_list: file_name = os.path.join(run_path, item) if os.path.exists(file_name): os.remove(file_name) return({'salz':salz, 'sala':sala})
def main(ifile, shp_file, center_lonlat, salz, sala, satellite, aerotype=1, altitude=0.01, visibility=15, band_need=['all'], path_out_radi=None, path_out_6s=None): ''' @description: 主程序 @ifile {str}: L1B swath文件 @shp_file {str}: 研究区域矢量文件 @center_lonlat {[lon, lat]}: 中心经纬度 @aerotype {int}: 气溶胶类型(默认大陆型) @altitude {float}: 海拔(km) @visibility {float}: 能见度(km) @band_need {list}: 所选波段, all表示全部处理 @path_6s {str}: 大气校正结果输出路径 @return: ''' # 设置环境变量 os.environ['MRTDATADIR'] = global_config['MRTDATADIR'] os.environ['PGSHOME'] = global_config['PGSHOME'] os.environ['MRTBINDIR'] = global_config['MRTBINDIR'] run_path = os.path.split(ifile)[0] # step 1: 获取hdf信息 SD_file = SD(ifile) sds_obj = SD_file.select('EV_250_Aggr500_RefSB') sds_info = sds_obj.attributes() scales = sds_info['radiance_scales'] offsets = sds_info['radiance_offsets'] sds_obj = SD_file.select('EV_500_RefSB') sds_info = sds_obj.attributes() scales_t = sds_info['radiance_scales'] offsets_t = sds_info['radiance_offsets'] for i in range(len(scales_t)): scales.append(scales_t[i]) offsets.append(offsets_t[i]) SD_file.end() nbands = len(scales) date_str = os.path.split(ifile)[1].split('.')[1] time_str = os.path.split(ifile)[1].split('.')[2] date_str = date_teanslator.jd_to_cale(date_str[1:]) year = int(date_str.split('.')[0]) month = int(date_str.split('.')[1]) day = int(date_str.split('.')[2]) hour = int(time_str[0:2]) minute = int(time_str[2:]) date = '%d/%d/%d %d:%d:00' % (year, month, day, hour, minute) sola_position = calc_sola_position.main(center_lonlat[0], center_lonlat[1], date) solz = sola_position[0] sola = sola_position[1] heg_bin = os.path.join(global_config['MRTBINDIR'], 'hegtool') os.system('cd %s && %s -h %s > heg.log' % (run_path, heg_bin, ifile)) info_file = os.path.join(run_path, 'HegHdr.hdr') if not (os.path.exists(info_file)): print('获取文件信息出错:%s' % ifile) return ('') else: lat_min = None lat_max = None lon_min = None lon_max = None pixel_x = None pixel_y = None with open(info_file, 'r') as fp: lines = fp.readlines() for line in lines: if 'SWATH_LAT_MIN' in line: lat_min = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_LAT_MAX' in line: lat_max = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_LON_MIN' in line: lon_min = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_LON_MAX' in line: lon_max = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_X_PIXEL_RES_DEGREES' in line: pixel_x = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_Y_PIXEL_RES_DEGREES' in line: pixel_y = float(re.findall(r'[\d.]+', line)[0]) if lat_min and lat_max and lon_min and lon_max and pixel_x and pixel_y: prm_file = os.path.join(run_path, 'HegSwath.prm') # 重投影 for i_band in range(nbands): modis_band = 'B%d' % (i_band + 1) if (modis_band in band_need) or ('all' in band_need): print('reprojection %s ...' % modis_band) out_file = ifile.replace('.hdf', '_reproj_' + modis_band + '.tif') if '.hdf' in ifile: if os.path.exists(out_file): os.remove(out_file) else: print('无法识别的文件格式:%s' % os.path.split(ifile)[1]) with open(prm_file, 'wb') as fp: fp.write(b'\nNUM_RUNS = 1\n\n') fp.write(b'BEGIN\n') fp.write( bytes('INPUT_FILENAME = %s\n' % ifile, 'utf-8')) fp.write(b'OBJECT_NAME = MODIS_SWATH_Type_L1B\n') if i_band >= 0 and i_band <= 1: fp.write(b'FIELD_NAME = EV_250_Aggr500_RefSB|\n') fp.write( bytes('BAND_NUMBER = %d\n' % (i_band + 1), 'utf-8')) else: fp.write(b'FIELD_NAME = EV_500_RefSB|\n') fp.write( bytes('BAND_NUMBER = %d\n' % (i_band - 1), 'utf-8')) fp.write( bytes('OUTPUT_PIXEL_SIZE_X = %f\n' % pixel_x, 'utf-8')) fp.write( bytes('OUTPUT_PIXEL_SIZE_Y = %f\n' % pixel_y, 'utf-8')) fp.write( bytes( 'SPATIAL_SUBSET_UL_CORNER = ( %f %f )\n' % (lat_max, lon_min), 'utf-8')) fp.write( bytes( 'SPATIAL_SUBSET_LR_CORNER = ( %f %f )\n' % (lat_min, lon_max), 'utf-8')) fp.write(b'OUTPUT_PROJECTION_TYPE = GEO\n') fp.write( bytes('OUTPUT_FILENAME = %s\n' % out_file, 'utf-8')) fp.write(b'OUTPUT_TYPE = GEO\n') fp.write(b'END\n\n') swtif_bin = os.path.join(global_config['MRTBINDIR'], 'swtif') os.system('cd %s && %s -P HegSwath.prm > heg.log' % (run_path, swtif_bin)) else: print('[Error] 未获得全部的所需信息') return (0) # 裁切与合并 if 'all' in band_need: raster_file = ifile.replace('.hdf', '_reproj_B1.tif') else: raster_file = ifile.replace('.hdf', '_reproj_' + band_need[0] + '.tif') if not (os.path.exists(raster_file)): return ('') out_file = raster_file.replace('.tif', '_cut.tif') cut_range = img_cut.main(raster_file, shp_file=shp_file, out_file=out_file) xsize = cut_range[1] - cut_range[0] ysize = cut_range[3] - cut_range[2] # 影像裁切 print('裁切...') for i_band in range(nbands): modis_band = 'B%d' % (i_band + 1) if (modis_band in band_need) or ('all' in band_need): raster_file = ifile.replace('.hdf', '_reproj_' + modis_band + '.tif') out_file = raster_file.replace('.tif', '_cut.tif') img_cut.main(raster_file, sub_lim=cut_range, out_file=out_file) # 辐射定标 print('辐射定标...') raster = gdal.Open(raster_file) date_str = '%d%02d%02d%02d%02d%02d' % (year, month, day, hour + 8, minute, 0) nrow = os.path.split(ifile)[1].split('.')[3] if satellite == 'AQUA': out_name = 'AQUA_MODIS_500_L2_%s_%s_00.tif' % (date_str, nrow) elif satellite == 'TERRA': out_name = 'TERRA_MODIS_500_L2_%s_%s_00.tif' % (date_str, nrow) else: print('[Error] 无法识别卫星类型') return (0) if os.path.exists(path_out_radi): raster_fn_out_radi = os.path.join(path_out_radi, out_name) driver = gdal.GetDriverByName('GTiff') target_ds = driver.Create(raster_fn_out_radi, xsize, ysize, nbands, gdal.GDT_Int16) target_ds.SetGeoTransform(raster.GetGeoTransform()) target_ds.SetProjection(raster.GetProjectionRef()) nan_mask = None for i_band in range(nbands): modis_band = 'B%d' % (i_band + 1) if (modis_band in band_need) or ('all' in band_need): raster_file = ifile.replace( '.hdf', '_reproj_' + modis_band + '.tif') out_file = raster_file.replace('.tif', '_cut.tif') raster_cut = gdal.Open(out_file) raster_data = ( raster_cut.GetRasterBand(1).ReadAsArray()).astype( np.int) if nan_mask is None: nan_mask = raster_data > 65530 raster_data[nan_mask] = -9999 target_ds.GetRasterBand(i_band + 1).WriteArray(raster_data) target_ds.GetRasterBand(i_band + 1).SetNoDataValue(-9999) raster_cut = None target_ds = None else: print('[Warning] without radiation-correction output!') # 大气校正 print('大气校正 ...') nan_mask = None driver = gdal.GetDriverByName('GTiff') raster_fn_out_6s = os.path.join(path_out_6s, out_name) target_ds = driver.Create(raster_fn_out_6s, xsize, ysize, nbands, gdal.GDT_Int16) target_ds.SetGeoTransform(raster.GetGeoTransform()) target_ds.SetProjection(raster.GetProjectionRef()) for i_band in range(nbands): modis_band = 'B%d' % (i_band + 1) if (modis_band in band_need) or ('all' in band_need): raster_file = ifile.replace('.hdf', '_reproj_' + modis_band + '.tif') out_file = raster_file.replace('.tif', '_cut.tif') raster_cut = gdal.Open(out_file) raster_data = raster_cut.GetRasterBand(1).ReadAsArray() if nan_mask is None: nan_mask = raster_data > 65530 raster_data = raster_data.astype(float) raster_data = scales[i_band] * (raster_data - offsets[i_band]) mtl_coef = { 'altitude': altitude, 'visibility': visibility, 'aero_type': aerotype, 'location': center_lonlat, 'month': month, 'day': day, 'solz': solz, 'sola': sola, 'salz': salz, 'sala': sala } wave_index = i_band + 42 data_tmp = (arms_corr(raster_data, mtl_coef, wave_index) * 10000).astype(np.int) data_tmp[nan_mask] = -9999 target_ds.GetRasterBand(i_band + 1).WriteArray(data_tmp) target_ds.GetRasterBand(i_band + 1).SetNoDataValue(-9999) raster_cut = None target_ds = None raster = None # 删除过程文件 for item in modis_band_list: file_name = ifile.replace('.hdf', '_reproj_' + item + '.tif') file_name_met = file_name.replace('.tif', '.tif.met') file_name_cut = ifile.replace('.hdf', '_reproj_' + item + '_cut.tif') if os.path.exists(file_name) and os.path.exists(file_name_met): os.remove(file_name) os.remove(file_name_met) if os.path.exists(file_name_cut): os.remove(file_name_cut) log_list = [ 'heg.log', 'swtif.log', 'HegSwath.prm', 'HegHdr.hdr', 'hegtool.log' ] for item in log_list: file_name = os.path.join(run_path, item) if os.path.exists(file_name): os.remove(file_name) return (raster_fn_out_6s)
def main(ifile, shp_file, center_lonlat, salz, sala, cut_range=None, aerotype=1, altitude=0.01, visibility=15, band_need=['all'], path_out=None): ''' @description: @ifile {str}: L1B swath文件 @shp_file {str}: 研究区域矢量文件 @center_lonlat {[lon, lat]}: 中心经纬度 @aerotype {int}: 气溶胶类型(默认大陆型) @altitude {float}: 海拔(km) @visibility {float}: 能见度(km) @return: ''' # 设置环境变量 os.environ['MRTDATADIR'] = global_config['MRTDATADIR'] os.environ['PGSHOME'] = global_config['PGSHOME'] os.environ['MRTBINDIR'] = global_config['MRTBINDIR'] run_path = os.path.split(ifile)[0] # step 1: 获取hdf信息 nbands = 16 SD_file = SD(ifile) scales = [] offsets = [] for i_band in range(nbands): if i_band + 1 == 9: sds_obj = SD_file.select('Reflectance_M%d' % (i_band + 1)) elif i_band + 1 >= 12: sds_obj = SD_file.select('BrightnessTemperature_M%d' % (i_band + 1)) else: sds_obj = SD_file.select('Radiance_M%d' % (i_band + 1)) sds_info = sds_obj.attributes() if 'Scale' in sds_info: scales.append(sds_info['Scale']) else: scales.append(1) if 'Offset' in sds_info: offsets.append(sds_info['Offset']) else: offsets.append(0) SD_file.end() date_str = os.path.split(ifile)[1].split('.')[1] time_str = os.path.split(ifile)[1].split('.')[2] date_str = date_teanslator.jd_to_cale(date_str[1:]) year = int(date_str.split('.')[0]) month = int(date_str.split('.')[1]) day = int(date_str.split('.')[2]) hour = int(time_str[0:2]) minute = int(time_str[2:]) date = '%d/%d/%d %d:%d:00' % (year, month, day, hour, minute) sola_position = calc_sola_position.main(center_lonlat[0], center_lonlat[1], date) solz = sola_position[0] sola = sola_position[1] heg_bin = os.path.join(global_config['MRTBINDIR'], 'hegtool') os.system('cd %s && %s -h %s > heg.log' % (run_path, heg_bin, ifile)) info_file = os.path.join(run_path, 'HegHdr.hdr') if not (os.path.exists(info_file)): print('获取文件信息出错:%s' % ifile) return (0) else: lat_min = None lat_max = None lon_min = None lon_max = None pixel_x = None pixel_y = None with open(info_file, 'r') as fp: lines = fp.readlines() for line in lines: if 'SWATH_LAT_MIN' in line: lat_min = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_LAT_MAX' in line: lat_max = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_LON_MIN' in line: lon_min = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_LON_MAX' in line: lon_max = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_X_PIXEL_RES_DEGREES' in line: pixel_x = float(re.findall(r'[\d.]+', line)[0]) elif 'SWATH_Y_PIXEL_RES_DEGREES' in line: pixel_y = float(re.findall(r'[\d.]+', line)[0]) if not (cut_range is None): lat_min = cut_range[2] lat_max = cut_range[3] lon_min = cut_range[0] lon_max = cut_range[1] if lat_min and lat_max and lon_min and lon_max and pixel_x and pixel_y: prm_file = os.path.join(run_path, 'HegSwath.prm') # 反射波段值重投影 for i_band in range(nbands): viirs_band = 'M%d' % (i_band + 1) if (viirs_band in band_need) or ('all' in band_need): print('reprojection %s ...' % viirs_band) out_file = ifile.replace('.hdf', '_reproj_' + viirs_band + '.tif') if '.hdf' in ifile: if os.path.exists(out_file): os.remove(out_file) else: print('无法识别的文件格式:%s' % os.path.split(ifile)[1]) with open(prm_file, 'wb') as fp: fp.write(b'\nNUM_RUNS = 1\n\n') fp.write(b'BEGIN\n') fp.write( bytes('INPUT_FILENAME = %s\n' % ifile, 'utf-8')) fp.write(b'OBJECT_NAME = VIIRS_EV_750M_SDR\n') if viirs_band == 'M9': fp.write( bytes( 'FIELD_NAME = Reflectance_M%d|\n' % (i_band + 1), 'utf-8')) elif viirs_band == 'M15' or viirs_band == 'M16': fp.write( bytes( 'FIELD_NAME = BrightnessTemperature_M%d|\n' % (i_band + 1), 'utf-8')) else: fp.write( bytes( 'FIELD_NAME = Radiance_M%d|\n' % (i_band + 1), 'utf-8')) fp.write(b'BAND_NUMBER = 1\n') fp.write( bytes('OUTPUT_PIXEL_SIZE_X = %f\n' % pixel_x, 'utf-8')) fp.write( bytes('OUTPUT_PIXEL_SIZE_Y = %f\n' % pixel_y, 'utf-8')) fp.write( bytes( 'SPATIAL_SUBSET_UL_CORNER = ( %f %f )\n' % (lat_max, lon_min), 'utf-8')) fp.write( bytes( 'SPATIAL_SUBSET_LR_CORNER = ( %f %f )\n' % (lat_min, lon_max), 'utf-8')) fp.write(b'OUTPUT_PROJECTION_TYPE = GEO\n') fp.write( bytes('OUTPUT_FILENAME = %s\n' % out_file, 'utf-8')) fp.write(b'OUTPUT_TYPE = GEO\n') fp.write(b'END\n\n') swtif_bin = os.path.join(global_config['MRTBINDIR'], 'swtif') os.system('cd %s && %s -P HegSwath.prm > heg.log' % (run_path, swtif_bin)) else: print('[Error] 未获得全部的所需信息') return (0) # 裁切与合并 if 'all' in band_need: raster_file = ifile.replace('.hdf', '_reproj_M1.tif') else: raster_file = ifile.replace('.hdf', '_reproj_' + band_need[0] + '.tif') out_file = raster_file.replace('.tif', '_cut.tif') cut_range = img_cut.main(raster_file, shp_file=shp_file, out_file=out_file) xsize = cut_range[1] - cut_range[0] ysize = cut_range[3] - cut_range[2] data_join = np.zeros([ysize, xsize, nbands]) print('大气校正 ...') for i_band in range(nbands): viirs_band = 'M%d' % (i_band + 1) if (viirs_band in band_need) or ('all' in band_need): raster_file = ifile.replace('.hdf', '_reproj_' + viirs_band + '.tif') out_file = raster_file.replace('.tif', '_cut.tif') img_cut.main(raster_file, sub_lim=cut_range, out_file=out_file) # 辐射定标和大气校正 raster = gdal.Open(out_file) raster_data = raster.GetRasterBand(1).ReadAsArray() raster_data = raster_data.astype(float) mask = raster_data >= 65530 raster_data = scales[i_band] * raster_data + offsets[i_band] mtl_coef = { 'altitude': altitude, 'visibility': visibility, 'aero_type': aerotype, 'location': center_lonlat, 'month': month, 'day': day, 'solz': solz, 'sola': sola, 'salz': salz, 'sala': sala } if i_band <= 11: wave_index = i_band + 149 else: wave_index = None if not (wave_index is None): if viirs_band == 'M9': tmp = raster_data else: tmp = arms_corr(raster_data, mtl_coef, wave_index) # tmp = raster_data tmp[mask] = 65535 data_join[:, :, i_band] = tmp else: tmp = raster_data tmp[mask] = 65535 data_join[:, :, i_band] = tmp driver = gdal.GetDriverByName('GTiff') if 'all' in band_need: raster_file = ifile.replace('.hdf', '_reproj_M1_cut.tif') else: raster_file = ifile.replace('.hdf', '_reproj_' + band_need[0] + '_cut.tif') raster = gdal.Open(raster_file) # 输出文件名 date_str = '%d%02d%02d%02d%02d%02d' % (year, month, day, hour + 8, minute, 0) nrow = os.path.split(ifile)[1].split('.')[3] out_name = 'NPP_VIIRS_750_L2_%s_%s_00.tif' % (date_str, nrow) if path_out is None: raster_fn_out = os.path.join(os.path.split(ifile)[0], out_name) else: raster_fn_out = os.path.join(path_out, out_name) target_ds = driver.Create(raster_fn_out, xsize, ysize, nbands, gdal.GDT_UInt16) target_ds.SetGeoTransform(raster.GetGeoTransform()) target_ds.SetProjection(raster.GetProjectionRef()) for i in range(nbands): if i < 11: target_ds.GetRasterBand(i + 1).WriteArray( (data_join[:, :, i] * 10000).astype(np.int)) else: target_ds.GetRasterBand(i + 1).WriteArray( (data_join[:, :, i] * 100).astype(np.int)) band = target_ds.GetRasterBand(i + 1) band.SetNoDataValue(65535) target_ds = None raster = None # 删除过程文件 for item in viirs_band_list: file_name = ifile.replace('.hdf', '_reproj_' + item + '.tif') file_name_met = file_name.replace('.tif', '.tif.met') file_name_cut = ifile.replace('.hdf', '_reproj_' + item + '_cut.tif') if os.path.exists(file_name) and os.path.exists(file_name_met): os.remove(file_name) os.remove(file_name_met) if os.path.exists(file_name_cut): os.remove(file_name_cut) log_list = [ 'heg.log', 'swtif.log', 'HegSwath.prm', 'HegHdr.hdr', 'hegtool.log' ] for item in log_list: file_name = os.path.join(run_path, item) if os.path.exists(file_name): os.remove(file_name) return (raster_fn_out)