#!/usr/bin/python ################################################################################# # # # $OPCSITE/python/convert_altimeter_hdf5_to_ascii.py # # # # Script to convert a NESDIS HDF5 altimeter file to the ascii required by # # nmap2. # # # # A note on the h5py import errors: # import h5 #/usr/lib64/python2.6/site-packages/h5py/__init__.py:34: RuntimeWarning: numpy.dtype size changed, may indicate binary incompatibility # import h5, h5a, h5d, h5f, h5fd, h5g, h5l, h5o, h5i, h5p, h5r, h5s, h5t, h5z # # # from the the Red Hat bugzilla page: # The warning does not affect execution of the python module. # A temporary workaround is to downgrade numpy to numpy-1.3.0-6.2.el6.x86_64. # # # Command line args: # # -f /path/and/file/name altimeter data in hdf5 # # # # History: # # F.Achorn/OPC 10/24/2016 Script satarted ################################################################################# import os import sys import getopt import logging import re import numpy as np import h5py import datetime def main(argv): # setup the logger set_log_file() # import the logger this_script_name=os.path.basename(sys.argv[0]) logger=logging.getLogger(this_script_name) infile="" try: opts, args = getopt.getopt(argv,"f:s:",["file="]) except getopt.GetoptError: logger.error("%s -f -s ", this_script_name) finish_script(11) logger.info('Command line opts, args:') if (len(opts) ==0): logger.error("No command line arguments given.\n%s -f -s ", this_script_name) finish_script(11) for opt, arg in opts: logger.info(' %s %s', opt, arg) if opt == '-f': if (os.path.isfile(arg)): infile=arg logger.info('Input file exists: %s',infile) else: logger.error('Input file does not exist: %s',infile) finish_script(21) if opt == '-s': if (arg == "s3a" or arg == "s3b"): satellite=arg logger.info('Satellite provided: %s',satellite) else: logger.error('Satellite unknown or not provided: %s',infile) finish_script(21) decode_hdf5(infile, satellite) finish_script(0) def set_log_file(log_base=''): #print ("in set_log_file") HOME=os.environ['HOME'] logDir=HOME+"/logs" this_script_name=os.path.basename(sys.argv[0]) logger=logging.getLogger(this_script_name) if (not os.path.isdir(logDir)): #make the directory #logger.info('Creating %s/logs', HOME) os.makedirs(logDir) print ('Creating %s/logs', HOME) #Check that the log_base is at least 4 characters long re_pattern=re.compile('\w{4}') if (not re_pattern.match(log_base)): #use the script name #this_script_no_ext=os.path.splitext(this_script_name)[0] log_base=os.path.splitext(os.path.basename(sys.argv[0]))[0] #Determine the day of the week day_of_week=datetime.datetime.today().weekday()+1 # set log name log_name=logDir + '/' + log_base + "_" + str(day_of_week) + ".log" print ("log name = " +log_name) #Setup the logger logger=logging.getLogger(this_script_name) logger.setLevel(logging.DEBUG) #create the file handle fh = logging.FileHandler(log_name) fh.setLevel(logging.INFO) #create the console logger to write to STDERR ch = logging.StreamHandler() ch.setLevel(logging.WARN) #ch.setLevel(logging.INFO) #set the log format for everything fh_formatter = logging.Formatter('%(process)d %(asctime)s %(levelname)s %(funcName)s| %(message)s') fh.setFormatter(fh_formatter) ch_formatter = logging.Formatter('%(levelname)s %(message)s') ch.setFormatter(ch_formatter) # add the hadlers to the logger logger.addHandler(fh) logger.addHandler(ch) logger.info('-------------------------------------------') logger.info('-------------------------------------------') logger.info('Starting %s', this_script_name) #logger.warn("Log started: %s", log_name) #logger.debug('debug message') #logger.info('info message') #logger.warn('warn message') #logger.error('error message') #logger.critical('critical message') #cleanup log from 1 week ago tomorrow=datetime.datetime.today() + datetime.timedelta(days=1) tomorrow_day_of_week = tomorrow.weekday()+1 tomorrow_log_name = logDir + '/' + log_base + "_" + str(tomorrow_day_of_week) + ".log" if (os.path.isfile(tomorrow_log_name)): os.remove(tomorrow_log_name) logger.warn("Removing tomorrow's log: $s", tomorrow_log_name) return() def finish_script(return_code): # import the logger this_script_name=os.path.basename(sys.argv[0]) logger=logging.getLogger(this_script_name) logger.info('Done with %s', this_script_name) logging.shutdown() sys.exit(return_code) def decode_hdf5(h5file, sat): this_script_name=os.path.basename(sys.argv[0]) logger=logging.getLogger(this_script_name) f = h5py.File(h5file, "r") # print f.name #root_group = f['/'] # for name in root_group: # print name # swh_dataset=f['/swh_ocean_01_ku'] # get the date of each Sentinel ob in "days since 2000-01-01 00:00:00.0" as an ascii file UTC_day_dataset=f.get('/UTC_day_01') UTC_sec_dataset=f.get('/UTC_sec_01') # We probably don't have np.datetime64 available (starts in numpy v1.7 # so the easiest way to do this is to convert the two integers into seconds since epoch # then string format the time later. date_count_start=datetime.date(2000,01,01).strftime('%s') #UTC_days_since_2000 = np.array(UTC_day_dataset)*(24*60*60) # convert the days to seconds - use floats UTC_days_since_2000 = np.array(UTC_day_dataset)*24.0*60.0*60.0 #print UTC_days_since_2000[0] UTC_seconds=np.array(UTC_sec_dataset) ob_date_epoch=np.array(UTC_days_since_2000+UTC_seconds+float(date_count_start)) #print UTC_seconds[0] #print date_count_start #print ob_date_epoch[0] #print datetime.datetime.utcfromtimestamp(ob_date_epoch[0]) swh_dataset=f.get('/swh_ocean_01_plrm_ku') #swh_dataset=f.get('/swh_ocean_01_ku') #convert to the right SI units, then to ft and kt. swh =np.array(swh_dataset)/1000.0*3.2808 wspd_dataset=f['/wind_speed_alt_01_plrm_ku'] #wspd_dataset=f['/wind_speed_alt_01_ku'] wspd=np.array(wspd_dataset)/100.0*1.9484 lat_dataset=f['/lat_01'] lat=np.array(lat_dataset)/1000000.0 lon_dataset=f['/lon_01'] lon=np.array(lon_dataset)/1000000.0 swh_qc_dataset=f.get('/swh_ocean_qual_01_plrm_ku') swh_qc=np.array(swh_qc_dataset) wspd_qc_dataset=f['/sig0_ocean_qual_01_plrm_ku'] wspd_qc=np.array(wspd_qc_dataset) # Longitude is in degrees East. Convert to positive for East and negatve for west. # find the mask where lon >180. # at those points, subtract from 360 W_hemi_mask = lon > 180.0 lon[W_hemi_mask] = -360+lon[W_hemi_mask] #write out the entries obs_dict = {} logger.info("%d obs in the file", len(lon)) for i in range(len(lon)): ob_date=datetime.datetime.utcfromtimestamp(ob_date_epoch[i]) ob_yyyymmddhh=ob_date.strftime('%Y%m%d%H') #print UTC_days_since_2000[i] #print ob_yyyymmddhh # Sometimes, we get bad data with the sgwh and wspd 107.50 and 638.43 (respectively). That works backward to 0.0327664 or 32.7664. if swh_qc[i] == 0: ob=" %4d %2d %2d %2d %2d %6.2f %7.2f %6.2f %7.2f"% (ob_date.year, ob_date.month, ob_date.day, ob_date.hour, ob_date.minute, lat[i], lon[i], swh[i], wspd[i]) # print (" %04d %2d %2d %2d %2d %6.2f %7.2f %6.2f %7.2f"% (ob_date.year, ob_date.month, ob_date.day, ob_date.hour, ob_date.minute, lat[i], lon[i], swh[i], wspd[i])) #print ob logger.debug(ob) # find and open the correct output file. Make any additions only if the exact ob isn't in the existing file if ob_yyyymmddhh in obs_dict: obs_dict[ob_yyyymmddhh].append(ob) else: obs_dict[ob_yyyymmddhh]=[ob] else: bad_ob=" %4d %2d %2d %2d %2d %6.2f %7.2f %6.2f %7.2f"% (ob_date.year, ob_date.month, ob_date.day, ob_date.hour, ob_date.minute, lat[i], lon[i], swh[i], wspd[i]) logger.info("QC'd ob. Not included: %s", bad_ob) # itterate through the obs dates we've found for date_key in obs_dict: # determin the nmap2 file name nmap2_file = sat + "_" + date_key + ".sgwh" # open the nmap2 file (should be in cwd if (os.path.isfile(nmap2_file)): logger.debug("reading %s", nmap2_file) with open(nmap2_file, 'r') as f: # read the data into a list. # f.readlines keeps the \n. Get rid of them old_list = f.read().splitlines() else: old_list = [] logger.info("old list = %d obs", len(old_list)) # concatenate the two obs lists new_list = old_list + obs_dict[date_key] logger.info("new list = %d obs", len(new_list)) # sort and uniq the list: new_sorted_list = sorted(set(new_list)) logger.info("new sorted list = %d obs", len(new_sorted_list)) # overwrite the file with the new list. with open(nmap2_file, 'w') as f: f.write('\n'.join(new_sorted_list)) if __name__ == "__main__": main(sys.argv[1:])