From fc9b557e4e5547b09c203d8af6a3d0d6118b9eff Mon Sep 17 00:00:00 2001 From: Geoff Cureton <geoff.cureton@ssec.wisc.edu> Date: Tue, 12 Sep 2017 19:02:31 +0000 Subject: [PATCH] Added scripts to convert local AIRS/MODIS and CrIS/VIIRS NetCDF fusion files into IFF files. --- utils/run_modis_airs_fusion_iff.py | 283 +++++++++++++++++++++++++++++ utils/run_viirs_cris_fusion_iff.py | 245 +++++++++++++++++++++++++ 2 files changed, 528 insertions(+) create mode 100644 utils/run_modis_airs_fusion_iff.py create mode 100644 utils/run_viirs_cris_fusion_iff.py diff --git a/utils/run_modis_airs_fusion_iff.py b/utils/run_modis_airs_fusion_iff.py new file mode 100644 index 0000000..9c1bade --- /dev/null +++ b/utils/run_modis_airs_fusion_iff.py @@ -0,0 +1,283 @@ +#!/usr/bin/env python +# encoding: utf-8 +""" +run_modis_airs_fusion_iff.py + + * DESCRIPTION: Locally executes the IFF on MODIS Aqua Fusion L1B files. + +Created by Geoff Cureton <geoff.cureton@ssec.wisc.edu> on 2017-05-25. +Copyright (c) 2017 University of Wisconsin SSEC. All rights reserved. +Licensed under GNU GPLv3. +""" + +import os +from os.path import basename, dirname, abspath, isdir, isfile, exists, join as pjoin +import sys +import shutil +from glob import glob +from copy import copy + +import time +from datetime import datetime, timedelta +from subprocess import check_output, check_call, CalledProcessError +import traceback +import logging + +# every module should have a LOG object +LOG = logging.getLogger(__file__) + +def setup_logging(verbosity): + LOG.debug("Verbosity is {}".format(verbosity)) + + levels = [logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG] + level = levels[verbosity if verbosity < 4 else 3] + + # Set up the logging + #console_logFormat = '%(asctime)s : %(name)-12s: %(levelname)-8s %(message)s' + #console_logFormat = '%(levelname)s:%(name)s:%(msg)s') # [%(filename)s:%(lineno)d]' + #console_logFormat = '%(asctime)s : %(funcName)s:%(lineno)d: %(message)s' + #console_logFormat = '%(message)s' + console_logFormat = '(%(levelname)s):%(filename)s:%(funcName)s:%(lineno)d: %(message)s' + #console_logFormat = '%(asctime)s : (%(levelname)s):%(filename)s:%(funcName)s:%(lineno)d:' \ + #' %(message)s' + + dateFormat = '%Y-%m-%d %H:%M:%S' + logging.basicConfig( + stream=sys.stdout, level=level, + format=console_logFormat, + datefmt=dateFormat) + +def create_dir(dir): + ''' + Create a directory + ''' + returned_dir = copy(dir) + LOG.debug("We want to create the dir {} ...".format(dir)) + + try: + if returned_dir is not None: + returned_dir_path = dirname(returned_dir) + returned_dir_base = basename(returned_dir) + LOG.debug("returned_dir_path = {}".format(returned_dir_path)) + LOG.debug("returned_dir_base = {}".format(returned_dir_base)) + returned_dir_path = '.' if returned_dir_path=="" else returned_dir_path + LOG.debug("returned_dir_path = {}".format(returned_dir_path)) + # Check if a directory and has write permissions... + if not exists(returned_dir) and os.access(returned_dir_path, os.W_OK): + LOG.debug("Creating directory {} ...".format(returned_dir)) + os.makedirs(returned_dir) + # Check if the created dir has write permissions + if not os.access(returned_dir, os.W_OK): + msg = "Created dir {} is not writable.".format(returned_dir) + raise SipsEnvironment(msg) + elif exists(returned_dir): + LOG.debug("Directory {} exists...".format(returned_dir)) + if not(isdir(returned_dir) and os.access(returned_dir, os.W_OK)): + msg = "Existing dir {} is not writable.".format(returned_dir) + raise SipsEnvironment(msg) + else: + raise SipsEnvironment("Cannot create {}".format(returned_dir)) + except SipsEnvironment: + LOG.debug("Unable to create {}".format(returned_dir)) + LOG.debug(traceback.format_exc()) + returned_dir = None + except OSError: + LOG.debug( + "Unable to create new dir '{}' in {}".format(returned_dir_base, returned_dir_path)) + LOG.debug(traceback.format_exc()) + returned_dir = None + except Exception: + LOG.warning("General error for {}".format(returned_dir)) + LOG.debug(traceback.format_exc()) + returned_dir = None + + LOG.debug('Final returned_dir = {}'.format(returned_dir)) + return returned_dir + + +def create_iff_filename(prefix, platform, dt, output_type='HDF4'): + + origin = 'ssec' + domain = 'fsn' + suffix = {'HDF4': '.hdf', 'NETCDF': '.nc'} + + begin_date = dt.strftime('d%Y%m%d') + begin_time = dt.strftime('t%H%M%S') + processed_time = datetime.now().strftime('c%Y%m%d%H%M%S') + + fn = '{}{}'.format('_'.join([prefix, platform, begin_date, begin_time, + processed_time, origin, domain]), + suffix[output_type]) + return fn + +def main(args): + ''' + Required arguments: + 1. input_dir : location of VGEOM and VL1B inputs + 2. output_type: HDF or NETCDF + 3. output_dir : Directory to place output files + ''' + verbosity = 2 + setup_logging(verbosity) + + input_dir = args[0] + output_type = args[1] + output_dir = args[2] + + LOG.info('input_dir = {}'.format(input_dir)) + LOG.info('output_type = {}'.format(output_type)) + LOG.info('output_dir = {}'.format(output_dir)) + + # Return a dictionary of input pairs + modis_geolocation_files = glob(pjoin(input_dir, 'MYD03*.hdf')) + modis_geolocation_files.sort() + modis_airs_fused_files = glob(pjoin(input_dir, 'MYD021KM*.hdf')) + modis_airs_fused_files.sort() + + input_dict = {} + + files_slice = slice(None) + #files_slice = slice(228,232) + + for fusion_file in modis_airs_fused_files[files_slice]: + granule_key = '_'.join(basename(fusion_file).split('_')[2:4]) + input_dict[granule_key] = {} + input_dict[granule_key]['VL1BM'] = fusion_file + + for geo_file in modis_geolocation_files[:]: + granule_key = '_'.join(basename(geo_file).split('_')[2:4]) + if granule_key in input_dict.keys(): + input_dict[granule_key]['VGEOM'] = geo_file + + granule_keys = input_dict.keys() + granule_keys.sort() + + rc = 0 + + # Create the output directory + current_dir = os.getcwd() + LOG.debug('Current directory is {}'.format(current_dir)) + create_dir(output_dir) + + # Set the granule length + granule_length = timedelta(minutes=6.) + + # Loop through the granule keys... + for granule_key in granule_keys: + + # Get the datetime object of the input files... + # VL1BM_snpp_d20150417_t235400_c20170401181430.nc + start_time = datetime.strptime(granule_key, 'd%Y%m%d_t%H%M%S') + end_time = start_time + granule_length - timedelta(seconds=1) + output_file = create_iff_filename('IFFSDR', 'aqua', start_time, output_type) + + LOG.info('granule_key = "{}", start_time, end_time = {}, {}, out_fn = {}'.format(granule_key, start_time, end_time, output_file)) + + geo_file = input_dict[granule_key]['VGEOM'] + l1b_file = input_dict[granule_key]['VL1BM'] + + cmd = 'python -m iff2.iff2 -{7} -o {0} --hdf4 aqua modis 1km {1:%Y%m%d} {2:%H%M%S} {3:%H%M%S}'.format( + pjoin(output_dir, output_file), + begin_time, + end_time, + geo_file, + l1b_file, + verbosity * 'v' + ) + + cmd = 'python -m iff2.iff2 -{5} -o {0} --hdf4 npp modis-nasa svm {1:%Y%m%d} {1:%H%M%S} {2:%H%M%S} {3} {4}'.format( + pjoin(output_dir, output_file), + start_time, + end_time, + geo_file, + l1b_file, + verbosity * 'v' + ) + LOG.debug('cmd = "{}"'.format(cmd)) + + try: + rc = check_call([cmd], shell=True, env=os.environ) + LOG.debug('check_call() return value: {}'.format(rc)) + except CalledProcessError as err: + rc = err.returncode + LOG.error("iff2.iff2 returned a value of {}".format(rc)) + return rc + + + #time.sleep(1.) + + return rc + + +if __name__ == '__main__': + args = sys.argv[1:] + + usage = \ + """ + Usage: 'run_modis_airs_fusion_iff.py <options> + where <options> are: + + 1. input_dir : location of VGEOM and VL1B inputs + 2. output_type: HDF4 or NETCDF + 3. output_dir : Directory to place output files + """ + + if len(args) != 3: + print(usage) + + sys.exit(main(args)) +################################################################################################### + + +for files in file_list: + + # Get the datetime object of the input files... + granule_date = basename(files).split('.')[1][1:] + granule_time = basename(files).split('.')[2] + granule_dt_str = '{}{}'.format(granule_date, granule_time) + dt = datetime.strptime(granule_dt_str, '%Y%j%H%M') + print('string = "{}", dt = {}'.format(granule_dt_str, dt)) + + # Ingest the regular MODIS Aqua files + example_local_prepare.local_execute_example( + dt, 'aqua', 'v2.5', 'ingested', False, format, False, False, 'NN', timedelta(0, 300), + skip_prepare=False, skip_execute=True) + + # Substitute the Fusion MODIS Aqua MYD021KM file for the ingested file + file_name = glob('inputs/MYD021KM.*hdf')[0] + file_link = 'inputs/in_1' + shutil.move(file_name, file_name + '.orig') + os.remove(file_link) + file_name = 'inputs/' + basename(files) + if 'MFF021KM' in basename(files): + file_name = file_name.replace('MFF021KM','MYD021KM') + if 'MFP021KM' in basename(files): + file_name = file_name.replace('MFP021KM','MYD021KM') + shutil.copyfile(files, file_name) + os.symlink(basename(file_name), file_link) + + #shutil.copyfile('inputs/context_with_options', + #'temp/context_with_options_{}'.format(granule_dt_str)) + #os.remove('inputs/context_with_options') + + # Create the IFF file from the Fusion MODIS Aqua file. + example_local_prepare.local_execute_example( + dt, 'aqua', 'v2.5', 'ingested', False, 'NETCDF', False, False, 'NN', timedelta(0, 300), + skip_prepare=True, skip_execute=False) + + # Save the new Fusion IFF file + IFF_file = glob('outputs/IFFSDR*.{}'.format(suffix))[0] + print("IFF file: {}".format(IFF_file)) + + new_IFF_file = basename(IFF_file).replace('_dev','_fsn') + + if 'MFF021KM' in basename(files): + new_IFF_file = 'saved/full/' + new_IFF_file.replace('_ssec_','_full_') + + if 'MFP021KM' in basename(files): + new_IFF_file = 'saved/partial/' + new_IFF_file.replace('_ssec_','_part_') + + print("Copying {} to {}".format(IFF_file, new_IFF_file)) + shutil.copyfile(IFF_file, new_IFF_file) + + #time.sleep(5.) diff --git a/utils/run_viirs_cris_fusion_iff.py b/utils/run_viirs_cris_fusion_iff.py new file mode 100644 index 0000000..63e2f0d --- /dev/null +++ b/utils/run_viirs_cris_fusion_iff.py @@ -0,0 +1,245 @@ +#!/usr/bin/env python +# encoding: utf-8 +""" +run_viirs_cris_fusion_iff.py + + * DESCRIPTION: Locally executes the IFF on VIIRS SNPP Fusion L1B files. + +Created by Geoff Cureton <geoff.cureton@ssec.wisc.edu> on 2017-09-11. +Copyright (c) 2017 University of Wisconsin SSEC. All rights reserved. +Licensed under GNU GPLv3. +""" + +import os +from os.path import basename, dirname, abspath, isdir, isfile, exists, join as pjoin +import sys +import shutil +from glob import glob +from copy import copy + +import time +from datetime import datetime, timedelta +from subprocess import check_output, check_call, CalledProcessError +import traceback +import logging + +# every module should have a LOG object +LOG = logging.getLogger(__file__) + +def setup_logging(verbosity): + LOG.debug("Verbosity is {}".format(verbosity)) + + levels = [logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG] + level = levels[verbosity if verbosity < 4 else 3] + + # Set up the logging + #console_logFormat = '%(asctime)s : %(name)-12s: %(levelname)-8s %(message)s' + #console_logFormat = '%(levelname)s:%(name)s:%(msg)s') # [%(filename)s:%(lineno)d]' + #console_logFormat = '%(asctime)s : %(funcName)s:%(lineno)d: %(message)s' + #console_logFormat = '%(message)s' + console_logFormat = '(%(levelname)s):%(filename)s:%(funcName)s:%(lineno)d: %(message)s' + #console_logFormat = '%(asctime)s : (%(levelname)s):%(filename)s:%(funcName)s:%(lineno)d:' \ + #' %(message)s' + + dateFormat = '%Y-%m-%d %H:%M:%S' + logging.basicConfig( + stream=sys.stdout, level=level, + format=console_logFormat, + datefmt=dateFormat) + +def create_dir(dir): + ''' + Create a directory + ''' + returned_dir = copy(dir) + LOG.debug("We want to create the dir {} ...".format(dir)) + + try: + if returned_dir is not None: + returned_dir_path = dirname(returned_dir) + returned_dir_base = basename(returned_dir) + LOG.debug("returned_dir_path = {}".format(returned_dir_path)) + LOG.debug("returned_dir_base = {}".format(returned_dir_base)) + returned_dir_path = '.' if returned_dir_path=="" else returned_dir_path + LOG.debug("returned_dir_path = {}".format(returned_dir_path)) + # Check if a directory and has write permissions... + if not exists(returned_dir) and os.access(returned_dir_path, os.W_OK): + LOG.debug("Creating directory {} ...".format(returned_dir)) + os.makedirs(returned_dir) + # Check if the created dir has write permissions + if not os.access(returned_dir, os.W_OK): + msg = "Created dir {} is not writable.".format(returned_dir) + raise SipsEnvironment(msg) + elif exists(returned_dir): + LOG.debug("Directory {} exists...".format(returned_dir)) + if not(isdir(returned_dir) and os.access(returned_dir, os.W_OK)): + msg = "Existing dir {} is not writable.".format(returned_dir) + raise SipsEnvironment(msg) + else: + raise SipsEnvironment("Cannot create {}".format(returned_dir)) + except SipsEnvironment: + LOG.debug("Unable to create {}".format(returned_dir)) + LOG.debug(traceback.format_exc()) + returned_dir = None + except OSError: + LOG.debug( + "Unable to create new dir '{}' in {}".format(returned_dir_base, returned_dir_path)) + LOG.debug(traceback.format_exc()) + returned_dir = None + except Exception: + LOG.warning("General error for {}".format(returned_dir)) + LOG.debug(traceback.format_exc()) + returned_dir = None + + LOG.debug('Final returned_dir = {}'.format(returned_dir)) + return returned_dir + + +def create_iff_filename(prefix, platform, dt, output_type='HDF4'): + + origin = 'ssec' + domain = 'fsn' + suffix = {'HDF4': '.hdf', 'NETCDF': '.nc'} + + begin_date = dt.strftime('d%Y%m%d') + begin_time = dt.strftime('t%H%M%S') + processed_time = datetime.now().strftime('c%Y%m%d%H%M%S') + + fn = '{}{}'.format('_'.join([prefix, platform, begin_date, begin_time, + processed_time, origin, domain]), + suffix[output_type]) + return fn + +def main(args): + ''' + Required arguments: + 1. input_dir : location of VGEOM and VL1B inputs + 2. output_type: HDF or NETCDF + 3. output_dir : Directory to place output files + ''' + verbosity = 2 + setup_logging(verbosity) + + input_dir = args[0] + output_type = args[1] + output_dir = args[2] + + LOG.info('input_dir = {}'.format(input_dir)) + LOG.info('output_type = {}'.format(output_type)) + LOG.info('output_dir = {}'.format(output_dir)) + + # Return a dictionary of input pairs + viirs_geolocation_files = glob(pjoin(input_dir, 'VGEOM*.nc')) + viirs_geolocation_files.sort() + viirs_cris_fused_files = glob(pjoin(input_dir, 'VL1BM*.nc')) + viirs_cris_fused_files.sort() + + input_dict = {} + + files_slice = slice(None) + #files_slice = slice(0,1) + + for fusion_file in viirs_cris_fused_files[files_slice]: + granule_key = '_'.join(basename(fusion_file).split('_')[2:4]) + input_dict[granule_key] = {} + input_dict[granule_key]['VL1BM'] = fusion_file + + for geo_file in viirs_geolocation_files[:]: + granule_key = '_'.join(basename(geo_file).split('_')[2:4]) + if granule_key in input_dict.keys(): + input_dict[granule_key]['VGEOM'] = geo_file + + granule_keys = input_dict.keys() + granule_keys.sort() + + rc = 0 + + # Create the output directory + current_dir = os.getcwd() + LOG.debug('Current directory is {}'.format(current_dir)) + create_dir(output_dir) + + # Set the granule length + granule_length = timedelta(minutes=6.) + LOG.debug('granule_length is {}'.format(granule_length)) + + # Get the current environment settings + env = os.environ + + # Loop through the granule keys... + for granule_key in granule_keys: + + # Get the datetime object of the input files... + start_time = datetime.strptime(granule_key, 'd%Y%m%d_t%H%M%S') + end_time = start_time + granule_length - timedelta(seconds=1) + output_file = create_iff_filename('IFFSVM', 'snpp', start_time, output_type) + #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DUMMY + #output_file = basename(glob(pjoin(output_dir, output_file.split('_c')[0]) + '*')[0]) + #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + LOG.info('granule_key = "{}", start_time, end_time = {}, {}, out_fn = {}'.format(granule_key, start_time, end_time, output_file)) + + geo_file = input_dict[granule_key]['VGEOM'] + l1b_file = input_dict[granule_key]['VL1BM'] + + # Create the IFF from the NASA VIIRS L1b files + cmd = 'python -m iff2.iff2 -{5} -o {0} --hdf4 npp viirs-nasa svm {1:%Y%m%d} {1:%H%M%S} {2:%H%M%S} {3} {4}'.format( + pjoin(output_dir, output_file), + start_time, + end_time, + geo_file, + l1b_file, + verbosity * 'v' + ) + LOG.debug('cmd = "{}"'.format(cmd)) + + try: + rc = check_call([cmd], shell=True, env=env) + LOG.debug('check_call() return value: {}'.format(rc)) + except CalledProcessError as err: + rc = err.returncode + LOG.error("iff2.iff2 returned a value of {}".format(rc)) + return rc + + # Apply the land water mask to the new IFF files + cmd = 'python -m demlw.ifflw -{1} {0}'.format( + pjoin(output_dir, output_file), + verbosity * 'v' + ) + LOG.debug('cmd = "{}"'.format(cmd)) + + # Location of the demlw data location + demlw_dir = '/mnt/software/flo/iff/landwater' + + try: + env['DEMLW_DIR'] = demlw_dir + env['LW_CACHE_FILE'] = pjoin(demlw_dir, 'lw-cache.npy') + rc = check_call([cmd], shell=True, env=env) + LOG.debug('check_call() return value: {}'.format(rc)) + except CalledProcessError as err: + rc = err.returncode + LOG.error("demlw.ifflw returned a value of {}".format(rc)) + return rc + + #time.sleep(1.) + + return rc + + +if __name__ == '__main__': + args = sys.argv[1:] + + usage = \ + """ + Usage: 'run_viirs_cris_fusion_iff.py <options> + where <options> are: + + 1. input_dir : location of VGEOM and VL1B inputs + 2. output_type: HDF4 or NETCDF + 3. output_dir : Directory to place output files + """ + + if len(args) != 3: + print(usage) + + sys.exit(main(args)) -- GitLab