def compute_LPET_ICESat2(INPUT_FILE, VERBOSE=False, MODE=0o775): #-- create logger for verbosity level loglevel = logging.INFO if VERBOSE else logging.CRITICAL logger = pyTMD.utilities.build_logger('pytmd', level=loglevel) #-- read data from input file logger.info('{0} -->'.format(INPUT_FILE)) IS2_atl03_mds, IS2_atl03_attrs, IS2_atl03_beams = read_HDF5_ATL03_main( INPUT_FILE, ATTRIBUTES=True) DIRECTORY = os.path.dirname(INPUT_FILE) #-- extract parameters from ICESat-2 ATLAS HDF5 file name rx = re.compile( r'(processed_)?(ATL\d{2})_(\d{4})(\d{2})(\d{2})(\d{2})' r'(\d{2})(\d{2})_(\d{4})(\d{2})(\d{2})_(\d{3})_(\d{2})(.*?).h5$') try: SUB, PRD, YY, MM, DD, HH, MN, SS, TRK, CYCL, GRAN, RL, VERS, AUX = rx.findall( INPUT_FILE).pop() except: #-- output long-period equilibrium tide HDF5 file (generic) fileBasename, fileExtension = os.path.splitext(INPUT_FILE) OUTPUT_FILE = '{0}_{1}{2}'.format(fileBasename, 'LPET', fileExtension) else: #-- output long-period equilibrium tide HDF5 file for ASAS/NSIDC granules args = (PRD, YY, MM, DD, HH, MN, SS, TRK, CYCL, GRAN, RL, VERS, AUX) file_format = '{0}_LPET_{1}{2}{3}{4}{5}{6}_{7}{8}{9}_{10}_{11}{12}.h5' OUTPUT_FILE = file_format.format(*args) #-- number of GPS seconds between the GPS epoch #-- and ATLAS Standard Data Product (SDP) epoch atlas_sdp_gps_epoch = IS2_atl03_mds['ancillary_data'][ 'atlas_sdp_gps_epoch'] #-- copy variables for outputting to HDF5 file IS2_atl03_tide = {} IS2_atl03_fill = {} IS2_atl03_dims = {} IS2_atl03_tide_attrs = {} #-- number of GPS seconds between the GPS epoch (1980-01-06T00:00:00Z UTC) #-- and ATLAS Standard Data Product (SDP) epoch (2018-01-01T00:00:00Z UTC) #-- Add this value to delta time parameters to compute full gps_seconds IS2_atl03_tide['ancillary_data'] = {} IS2_atl03_tide_attrs['ancillary_data'] = {} for key in ['atlas_sdp_gps_epoch']: #-- get each HDF5 variable IS2_atl03_tide['ancillary_data'][key] = IS2_atl03_mds[ 'ancillary_data'][key] #-- Getting attributes of group and included variables IS2_atl03_tide_attrs['ancillary_data'][key] = {} for att_name, att_val in IS2_atl03_attrs['ancillary_data'][key].items( ): IS2_atl03_tide_attrs['ancillary_data'][key][att_name] = att_val #-- for each input beam within the file for gtx in sorted(IS2_atl03_beams): #-- output data dictionaries for beam IS2_atl03_tide[gtx] = dict(geolocation={}, geophys_corr={}) IS2_atl03_fill[gtx] = dict(geolocation={}, geophys_corr={}) IS2_atl03_dims[gtx] = dict(geolocation={}, geophys_corr={}) IS2_atl03_tide_attrs[gtx] = dict(geolocation={}, geophys_corr={}) #-- read data and attributes for beam val, attrs = read_HDF5_ATL03_beam(INPUT_FILE, gtx, ATTRIBUTES=True) #-- number of segments n_seg = len(val['geolocation']['segment_id']) #-- extract variables for computing equilibrium tides segment_id = val['geolocation']['segment_id'].copy() delta_time = val['geolocation']['delta_time'].copy() lon = val['geolocation']['reference_photon_lon'].copy() lat = val['geolocation']['reference_photon_lat'].copy() #-- invalid value fv = attrs['geolocation']['sigma_h']['_FillValue'] #-- convert time from ATLAS SDP to days relative to Jan 1, 1992 gps_seconds = atlas_sdp_gps_epoch + delta_time leap_seconds = pyTMD.time.count_leap_seconds(gps_seconds) tide_time = pyTMD.time.convert_delta_time(gps_seconds - leap_seconds, epoch1=(1980, 1, 6, 0, 0, 0), epoch2=(1992, 1, 1, 0, 0, 0), scale=1.0 / 86400.0) #-- interpolate delta times from calendar dates to tide time delta_file = pyTMD.utilities.get_data_path( ['data', 'merged_deltat.data']) deltat = calc_delta_time(delta_file, tide_time) #-- predict long-period equilibrium tides at latitudes and time tide_lpe = compute_equilibrium_tide(tide_time + deltat, lat) #-- group attributes for beam IS2_atl03_tide_attrs[gtx]['Description'] = attrs['Description'] IS2_atl03_tide_attrs[gtx]['atlas_pce'] = attrs['atlas_pce'] IS2_atl03_tide_attrs[gtx]['atlas_beam_type'] = attrs['atlas_beam_type'] IS2_atl03_tide_attrs[gtx]['groundtrack_id'] = attrs['groundtrack_id'] IS2_atl03_tide_attrs[gtx]['atmosphere_profile'] = attrs[ 'atmosphere_profile'] IS2_atl03_tide_attrs[gtx]['atlas_spot_number'] = attrs[ 'atlas_spot_number'] IS2_atl03_tide_attrs[gtx]['sc_orientation'] = attrs['sc_orientation'] #-- group attributes for geolocation IS2_atl03_tide_attrs[gtx]['geolocation']['Description'] = ( "Contains parameters related to " "geolocation. The rate of all of these parameters is at the rate corresponding to the " "ICESat-2 Geolocation Along Track Segment interval (nominally 20 m along-track)." ) IS2_atl03_tide_attrs[gtx]['geolocation']['data_rate'] = ( "Data within this group are " "stored at the ICESat-2 20m segment rate.") #-- group attributes for geophys_corr IS2_atl03_tide_attrs[gtx]['geophys_corr']['Description'] = ( "Contains parameters used to " "correct photon heights for geophysical effects, such as tides. These parameters are " "posted at the same interval as the ICESat-2 Geolocation Along-Track Segment interval " "(nominally 20m along-track).") IS2_atl03_tide_attrs[gtx]['geophys_corr']['data_rate'] = ( "These parameters are stored at " "the ICESat-2 Geolocation Along Track Segment rate (nominally every 20 m along-track)." ) #-- geolocation, time and segment ID #-- delta time in geolocation group IS2_atl03_tide[gtx]['geolocation']['delta_time'] = delta_time IS2_atl03_fill[gtx]['geolocation']['delta_time'] = None IS2_atl03_dims[gtx]['geolocation']['delta_time'] = None IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time'] = {} IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time'][ 'units'] = "seconds since 2018-01-01" IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time'][ 'long_name'] = "Elapsed GPS seconds" IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time'][ 'standard_name'] = "time" IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time'][ 'calendar'] = "standard" IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time']['description'] = ( "Elapsed seconds " "from the ATLAS SDP GPS Epoch, corresponding to the transmit time of the reference " "photon. The ATLAS Standard Data Products (SDP) epoch offset is defined within " "/ancillary_data/atlas_sdp_gps_epoch as the number of GPS seconds between the GPS epoch " "(1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP epoch. By adding the offset " "contained within atlas_sdp_gps_epoch to delta time parameters, the time in gps_seconds " "relative to the GPS epoch can be computed.") IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time']['coordinates'] = \ "segment_id reference_photon_lat reference_photon_lon" #-- delta time in geophys_corr group IS2_atl03_tide[gtx]['geophys_corr']['delta_time'] = delta_time IS2_atl03_fill[gtx]['geophys_corr']['delta_time'] = None IS2_atl03_dims[gtx]['geophys_corr']['delta_time'] = None IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time'] = {} IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time'][ 'units'] = "seconds since 2018-01-01" IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time'][ 'long_name'] = "Elapsed GPS seconds" IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time'][ 'standard_name'] = "time" IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time'][ 'calendar'] = "standard" IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time']['description'] = ( "Elapsed seconds " "from the ATLAS SDP GPS Epoch, corresponding to the transmit time of the reference " "photon. The ATLAS Standard Data Products (SDP) epoch offset is defined within " "/ancillary_data/atlas_sdp_gps_epoch as the number of GPS seconds between the GPS epoch " "(1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP epoch. By adding the offset " "contained within atlas_sdp_gps_epoch to delta time parameters, the time in gps_seconds " "relative to the GPS epoch can be computed.") IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time']['coordinates'] = ( "../geolocation/segment_id " "../geolocation/reference_photon_lat ../geolocation/reference_photon_lon" ) #-- latitude IS2_atl03_tide[gtx]['geolocation']['reference_photon_lat'] = lat IS2_atl03_fill[gtx]['geolocation']['reference_photon_lat'] = None IS2_atl03_dims[gtx]['geolocation']['reference_photon_lat'] = [ 'delta_time' ] IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'] = {} IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'units'] = "degrees_north" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'contentType'] = "physicalMeasurement" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'long_name'] = "Latitude" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'standard_name'] = "latitude" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'description'] = ( "Latitude of each " "reference photon. Computed from the ECF Cartesian coordinates of the bounce point." ) IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'valid_min'] = -90.0 IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'valid_max'] = 90.0 IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat']['coordinates'] = \ "segment_id delta_time reference_photon_lon" #-- longitude IS2_atl03_tide[gtx]['geolocation']['reference_photon_lon'] = lon IS2_atl03_fill[gtx]['geolocation']['reference_photon_lon'] = None IS2_atl03_dims[gtx]['geolocation']['reference_photon_lon'] = [ 'delta_time' ] IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'] = {} IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'units'] = "degrees_east" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'contentType'] = "physicalMeasurement" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'long_name'] = "Longitude" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'standard_name'] = "longitude" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'description'] = ( "Longitude of each " "reference photon. Computed from the ECF Cartesian coordinates of the bounce point." ) IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'valid_min'] = -180.0 IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'valid_max'] = 180.0 IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon']['coordinates'] = \ "segment_id delta_time reference_photon_lat" #-- segment ID IS2_atl03_tide[gtx]['geolocation']['segment_id'] = segment_id IS2_atl03_fill[gtx]['geolocation']['segment_id'] = None IS2_atl03_dims[gtx]['geolocation']['segment_id'] = ['delta_time'] IS2_atl03_tide_attrs[gtx]['geolocation']['segment_id'] = {} IS2_atl03_tide_attrs[gtx]['geolocation']['segment_id']['units'] = "1" IS2_atl03_tide_attrs[gtx]['geolocation']['segment_id'][ 'contentType'] = "referenceInformation" IS2_atl03_tide_attrs[gtx]['geolocation']['segment_id'][ 'long_name'] = "Along-track segment ID number" IS2_atl03_tide_attrs[gtx]['geolocation']['segment_id']['description'] = ( "A 7 digit number " "identifying the along-track geolocation segment number. These are sequential, starting with " "1 for the first segment after an ascending equatorial crossing node. Equal to the segment_id for " "the second of the two 20m ATL03 segments included in the 40m ATL03 segment" ) IS2_atl03_tide_attrs[gtx]['geolocation']['segment_id']['coordinates'] = \ "delta_time reference_photon_lat reference_photon_lon" #-- computed long-period equilibrium tide IS2_atl03_tide[gtx]['geophys_corr']['tide_equilibrium'] = tide_lpe IS2_atl03_fill[gtx]['geophys_corr']['tide_equilibrium'] = None IS2_atl03_dims[gtx]['geophys_corr']['tide_equilibrium'] = [ 'delta_time' ] IS2_atl03_tide_attrs[gtx]['geophys_corr']['tide_equilibrium'] = {} IS2_atl03_tide_attrs[gtx]['geophys_corr']['tide_equilibrium'][ 'units'] = "meters" IS2_atl03_tide_attrs[gtx]['geophys_corr']['tide_equilibrium'][ 'contentType'] = "referenceInformation" IS2_atl03_tide_attrs[gtx]['geophys_corr']['tide_equilibrium']['long_name'] = \ "Long Period Equilibrium Tide" IS2_atl03_tide_attrs[gtx]['geophys_corr']['tide_equilibrium'][ 'description'] = ( "Long-period " "equilibrium tidal elevation from the summation of fifteen tidal spectral lines" ) IS2_atl03_tide_attrs[gtx]['geophys_corr']['tide_equilibrium']['reference'] = \ "https://doi.org/10.1111/j.1365-246X.1973.tb03420.x" IS2_atl03_tide_attrs[gtx]['geophys_corr']['tide_equilibrium']['coordinates'] = \ ("../geolocation/segment_id ../geolocation/delta_time " "../geolocation/reference_photon_lat ../geolocation/reference_photon_lon") #-- print file information logger.info('\t{0}'.format(OUTPUT_FILE)) HDF5_ATL03_tide_write(IS2_atl03_tide, IS2_atl03_tide_attrs, CLOBBER=True, INPUT=os.path.basename(INPUT_FILE), FILL_VALUE=IS2_atl03_fill, DIMENSIONS=IS2_atl03_dims, FILENAME=os.path.join(DIRECTORY, OUTPUT_FILE)) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY, OUTPUT_FILE), MODE)
def compute_LPET_ICESat2(INPUT_FILE, VERBOSE=False, MODE=0o775): #-- create logger for verbosity level loglevel = logging.INFO if VERBOSE else logging.CRITICAL logger = pyTMD.utilities.build_logger('pytmd',level=loglevel) #-- read data from input file logger.info('{0} -->'.format(INPUT_FILE)) IS2_atl11_mds,IS2_atl11_attrs,IS2_atl11_pairs = read_HDF5_ATL11(INPUT_FILE, ATTRIBUTES=True, CROSSOVERS=True) DIRECTORY = os.path.dirname(INPUT_FILE) #-- extract parameters from ICESat-2 ATLAS HDF5 file name rx = re.compile(r'(processed_)?(ATL\d{2})_(\d{4})(\d{2})_(\d{2})(\d{2})_' r'(\d{3})_(\d{2})(.*?).h5$') try: SUB,PRD,TRK,GRAN,SCYC,ECYC,RL,VERS,AUX = rx.findall(INPUT_FILE).pop() except: #-- output long-period equilibrium tide HDF5 file (generic) fileBasename,fileExtension = os.path.splitext(INPUT_FILE) OUTPUT_FILE = '{0}_{1}{2}'.format(fileBasename,'LPET',fileExtension) else: #-- output long-period equilibrium tide HDF5 file for ASAS/NSIDC granules args = (PRD,TRK,GRAN,SCYC,ECYC,RL,VERS,AUX) file_format = '{0}_LPET_{1}{2}_{3}{4}_{5}_{6}{7}.h5' OUTPUT_FILE = file_format.format(*args) #-- number of GPS seconds between the GPS epoch #-- and ATLAS Standard Data Product (SDP) epoch atlas_sdp_gps_epoch = IS2_atl11_mds['ancillary_data']['atlas_sdp_gps_epoch'] #-- delta time (TT - UT1) file delta_file = pyTMD.utilities.get_data_path(['data','merged_deltat.data']) #-- copy variables for outputting to HDF5 file IS2_atl11_tide = {} IS2_atl11_fill = {} IS2_atl11_dims = {} IS2_atl11_tide_attrs = {} #-- number of GPS seconds between the GPS epoch (1980-01-06T00:00:00Z UTC) #-- and ATLAS Standard Data Product (SDP) epoch (2018-01-01T00:00:00Z UTC) #-- Add this value to delta time parameters to compute full gps_seconds IS2_atl11_tide['ancillary_data'] = {} IS2_atl11_tide_attrs['ancillary_data'] = {} for key in ['atlas_sdp_gps_epoch']: #-- get each HDF5 variable IS2_atl11_tide['ancillary_data'][key] = IS2_atl11_mds['ancillary_data'][key] #-- Getting attributes of group and included variables IS2_atl11_tide_attrs['ancillary_data'][key] = {} for att_name,att_val in IS2_atl11_attrs['ancillary_data'][key].items(): IS2_atl11_tide_attrs['ancillary_data'][key][att_name] = att_val #-- HDF5 group name for across-track data XT = 'crossing_track_data' #-- for each input beam pair within the file for ptx in sorted(IS2_atl11_pairs): #-- output data dictionaries for beam IS2_atl11_tide[ptx] = dict(cycle_stats=collections.OrderedDict(), crossing_track_data=collections.OrderedDict()) IS2_atl11_fill[ptx] = dict(cycle_stats={},crossing_track_data={}) IS2_atl11_dims[ptx] = dict(cycle_stats={},crossing_track_data={}) IS2_atl11_tide_attrs[ptx] = dict(cycle_stats={},crossing_track_data={}) #-- extract along-track and across-track variables ref_pt = {} latitude = {} longitude = {} delta_time = {} #-- along-track (AT) reference point, latitude, longitude and time ref_pt['AT'] = IS2_atl11_mds[ptx]['ref_pt'].copy() latitude['AT'] = np.ma.array(IS2_atl11_mds[ptx]['latitude'], fill_value=IS2_atl11_attrs[ptx]['latitude']['_FillValue']) longitude['AT'] = np.ma.array(IS2_atl11_mds[ptx]['longitude'], fill_value=IS2_atl11_attrs[ptx]['longitude']['_FillValue']) delta_time['AT'] = np.ma.array(IS2_atl11_mds[ptx]['delta_time'], fill_value=IS2_atl11_attrs[ptx]['delta_time']['_FillValue']) #-- across-track (XT) reference point, latitude, longitude and time ref_pt['XT'] = IS2_atl11_mds[ptx][XT]['ref_pt'].copy() latitude['XT'] = np.ma.array(IS2_atl11_mds[ptx][XT]['latitude'], fill_value=IS2_atl11_attrs[ptx][XT]['latitude']['_FillValue']) longitude['XT'] = np.ma.array(IS2_atl11_mds[ptx][XT]['longitude'], fill_value=IS2_atl11_attrs[ptx][XT]['longitude']['_FillValue']) delta_time['XT'] = np.ma.array(IS2_atl11_mds[ptx][XT]['delta_time'], fill_value=IS2_atl11_attrs[ptx][XT]['delta_time']['_FillValue']) #-- number of average segments and number of included cycles #-- fill_value for invalid heights and corrections fv = IS2_atl11_attrs[ptx]['h_corr']['_FillValue'] #-- shape of along-track and across-track data n_points,n_cycles = delta_time['AT'].shape n_cross, = delta_time['XT'].shape #-- allocate for output long-period equilibrium tide variables tide_lpe = {} #-- along-track (AT) tides tide_lpe['AT'] = np.ma.empty((n_points,n_cycles),fill_value=fv) tide_lpe['AT'].mask = (delta_time['AT'] == delta_time['AT'].fill_value) #-- across-track (XT) tides tide_lpe['XT'] = np.ma.empty((n_cross),fill_value=fv) tide_lpe['XT'].mask = (delta_time['XT'] == delta_time['XT'].fill_value) #-- calculate tides for along-track and across-track data for track in ['AT','XT']: #-- convert time from ATLAS SDP to days relative to Jan 1, 1992 gps_seconds = atlas_sdp_gps_epoch + delta_time[track] leap_seconds = pyTMD.time.count_leap_seconds(gps_seconds) tide_time = pyTMD.time.convert_delta_time(gps_seconds-leap_seconds, epoch1=(1980,1,6,0,0,0), epoch2=(1992,1,1,0,0,0), scale=1.0/86400.0) #-- interpolate delta times from calendar dates to tide time delta_file = pyTMD.utilities.get_data_path(['data','merged_deltat.data']) deltat = calc_delta_time(delta_file, tide_time) #-- calculate long-period equilibrium tides for track type if (track == 'AT'): #-- calculate LPET for each cycle if along-track for cycle in range(n_cycles): #-- find valid time and spatial points for cycle valid, = np.nonzero(~tide_lpe[track].mask[:,cycle]) #-- predict long-period equilibrium tides at latitudes and time t = tide_time[valid,cycle] + deltat[valid,cycle] tide_lpe[track].data[valid,cycle] = compute_equilibrium_tide(t, latitude[track][valid]) elif (track == 'XT'): #-- find valid time and spatial points for cycle valid, = np.nonzero(~tide_lpe[track].mask[:]) #-- predict long-period equilibrium tides at latitudes and time t = tide_time[valid] + deltat[valid] tide_lpe[track].data[valid] = compute_equilibrium_tide(t, latitude[track][valid]) #-- replace masked and nan values with fill value invalid = np.nonzero(np.isnan(tide_lpe[track].data) | tide_lpe[track].mask) tide_lpe[track].data[invalid] = tide_lpe[track].fill_value tide_lpe[track].mask[invalid] = True #-- group attributes for beam IS2_atl11_tide_attrs[ptx]['description'] = ('Contains the primary science parameters ' 'for this data set') IS2_atl11_tide_attrs[ptx]['beam_pair'] = IS2_atl11_attrs[ptx]['beam_pair'] IS2_atl11_tide_attrs[ptx]['ReferenceGroundTrack'] = IS2_atl11_attrs[ptx]['ReferenceGroundTrack'] IS2_atl11_tide_attrs[ptx]['first_cycle'] = IS2_atl11_attrs[ptx]['first_cycle'] IS2_atl11_tide_attrs[ptx]['last_cycle'] = IS2_atl11_attrs[ptx]['last_cycle'] IS2_atl11_tide_attrs[ptx]['equatorial_radius'] = IS2_atl11_attrs[ptx]['equatorial_radius'] IS2_atl11_tide_attrs[ptx]['polar_radius'] = IS2_atl11_attrs[ptx]['polar_radius'] #-- geolocation, time and reference point #-- reference point IS2_atl11_tide[ptx]['ref_pt'] = ref_pt['AT'].copy() IS2_atl11_fill[ptx]['ref_pt'] = None IS2_atl11_dims[ptx]['ref_pt'] = None IS2_atl11_tide_attrs[ptx]['ref_pt'] = collections.OrderedDict() IS2_atl11_tide_attrs[ptx]['ref_pt']['units'] = "1" IS2_atl11_tide_attrs[ptx]['ref_pt']['contentType'] = "referenceInformation" IS2_atl11_tide_attrs[ptx]['ref_pt']['long_name'] = "Reference point number" IS2_atl11_tide_attrs[ptx]['ref_pt']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['ref_pt']['description'] = ("The reference point is the " "7 digit segment_id number corresponding to the center of the ATL06 data used " "for each ATL11 point. These are sequential, starting with 1 for the first " "segment after an ascending equatorial crossing node.") IS2_atl11_tide_attrs[ptx]['ref_pt']['coordinates'] = \ "delta_time latitude longitude" #-- cycle_number IS2_atl11_tide[ptx]['cycle_number'] = IS2_atl11_mds[ptx]['cycle_number'].copy() IS2_atl11_fill[ptx]['cycle_number'] = None IS2_atl11_dims[ptx]['cycle_number'] = None IS2_atl11_tide_attrs[ptx]['cycle_number'] = collections.OrderedDict() IS2_atl11_tide_attrs[ptx]['cycle_number']['units'] = "1" IS2_atl11_tide_attrs[ptx]['cycle_number']['long_name'] = "Orbital cycle number" IS2_atl11_tide_attrs[ptx]['cycle_number']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['cycle_number']['description'] = ("Number of 91-day periods " "that have elapsed since ICESat-2 entered the science orbit. Each of the 1,387 " "reference ground track (RGTs) is targeted in the polar regions once " "every 91 days.") #-- delta time IS2_atl11_tide[ptx]['delta_time'] = delta_time['AT'].copy() IS2_atl11_fill[ptx]['delta_time'] = delta_time['AT'].fill_value IS2_atl11_dims[ptx]['delta_time'] = ['ref_pt','cycle_number'] IS2_atl11_tide_attrs[ptx]['delta_time'] = collections.OrderedDict() IS2_atl11_tide_attrs[ptx]['delta_time']['units'] = "seconds since 2018-01-01" IS2_atl11_tide_attrs[ptx]['delta_time']['long_name'] = "Elapsed GPS seconds" IS2_atl11_tide_attrs[ptx]['delta_time']['standard_name'] = "time" IS2_atl11_tide_attrs[ptx]['delta_time']['calendar'] = "standard" IS2_atl11_tide_attrs[ptx]['delta_time']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['delta_time']['description'] = ("Number of GPS " "seconds since the ATLAS SDP epoch. The ATLAS Standard Data Products (SDP) epoch offset " "is defined within /ancillary_data/atlas_sdp_gps_epoch as the number of GPS seconds " "between the GPS epoch (1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP epoch. By " "adding the offset contained within atlas_sdp_gps_epoch to delta time parameters, the " "time in gps_seconds relative to the GPS epoch can be computed.") IS2_atl11_tide_attrs[ptx]['delta_time']['coordinates'] = \ "ref_pt cycle_number latitude longitude" #-- latitude IS2_atl11_tide[ptx]['latitude'] = latitude['AT'].copy() IS2_atl11_fill[ptx]['latitude'] = latitude['AT'].fill_value IS2_atl11_dims[ptx]['latitude'] = ['ref_pt'] IS2_atl11_tide_attrs[ptx]['latitude'] = collections.OrderedDict() IS2_atl11_tide_attrs[ptx]['latitude']['units'] = "degrees_north" IS2_atl11_tide_attrs[ptx]['latitude']['contentType'] = "physicalMeasurement" IS2_atl11_tide_attrs[ptx]['latitude']['long_name'] = "Latitude" IS2_atl11_tide_attrs[ptx]['latitude']['standard_name'] = "latitude" IS2_atl11_tide_attrs[ptx]['latitude']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['latitude']['description'] = ("Center latitude of " "selected segments") IS2_atl11_tide_attrs[ptx]['latitude']['valid_min'] = -90.0 IS2_atl11_tide_attrs[ptx]['latitude']['valid_max'] = 90.0 IS2_atl11_tide_attrs[ptx]['latitude']['coordinates'] = \ "ref_pt delta_time longitude" #-- longitude IS2_atl11_tide[ptx]['longitude'] = longitude['AT'].copy() IS2_atl11_fill[ptx]['longitude'] = longitude['AT'].fill_value IS2_atl11_dims[ptx]['longitude'] = ['ref_pt'] IS2_atl11_tide_attrs[ptx]['longitude'] = collections.OrderedDict() IS2_atl11_tide_attrs[ptx]['longitude']['units'] = "degrees_east" IS2_atl11_tide_attrs[ptx]['longitude']['contentType'] = "physicalMeasurement" IS2_atl11_tide_attrs[ptx]['longitude']['long_name'] = "Longitude" IS2_atl11_tide_attrs[ptx]['longitude']['standard_name'] = "longitude" IS2_atl11_tide_attrs[ptx]['longitude']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['longitude']['description'] = ("Center longitude of " "selected segments") IS2_atl11_tide_attrs[ptx]['longitude']['valid_min'] = -180.0 IS2_atl11_tide_attrs[ptx]['longitude']['valid_max'] = 180.0 IS2_atl11_tide_attrs[ptx]['longitude']['coordinates'] = \ "ref_pt delta_time latitude" #-- cycle statistics variables IS2_atl11_tide_attrs[ptx]['cycle_stats']['Description'] = ("The cycle_stats subgroup " "contains summary information about segments for each reference point, including " "the uncorrected mean heights for reference surfaces, blowing snow and cloud " "indicators, and geolocation and height misfit statistics.") IS2_atl11_tide_attrs[ptx]['cycle_stats']['data_rate'] = ("Data within this group " "are stored at the average segment rate.") #-- computed long-period equilibrium tide IS2_atl11_tide[ptx]['cycle_stats']['tide_equilibrium'] = tide_lpe['AT'].copy() IS2_atl11_fill[ptx]['cycle_stats']['tide_equilibrium'] = tide_lpe['AT'].fill_value IS2_atl11_dims[ptx]['cycle_stats']['tide_equilibrium'] = ['ref_pt','cycle_number'] IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium'] = collections.OrderedDict() IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium']['units'] = "meters" IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium']['contentType'] = "referenceInformation" IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium']['long_name'] = \ "Long Period Equilibrium Tide" IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium']['description'] = ("Long-period " "equilibrium tidal elevation from the summation of fifteen tidal spectral lines") IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium']['reference'] = \ "https://doi.org/10.1111/j.1365-246X.1973.tb03420.x" IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium']['coordinates'] = \ "../ref_pt ../cycle_number ../delta_time ../latitude ../longitude" #-- crossing track variables IS2_atl11_tide_attrs[ptx][XT]['Description'] = ("The crossing_track_data " "subgroup contains elevation data at crossover locations. These are " "locations where two ICESat-2 pair tracks cross, so data are available " "from both the datum track, for which the granule was generated, and " "from the crossing track.") IS2_atl11_tide_attrs[ptx][XT]['data_rate'] = ("Data within this group are " "stored at the average segment rate.") #-- reference point IS2_atl11_tide[ptx][XT]['ref_pt'] = ref_pt['XT'].copy() IS2_atl11_fill[ptx][XT]['ref_pt'] = None IS2_atl11_dims[ptx][XT]['ref_pt'] = None IS2_atl11_tide_attrs[ptx][XT]['ref_pt'] = collections.OrderedDict() IS2_atl11_tide_attrs[ptx][XT]['ref_pt']['units'] = "1" IS2_atl11_tide_attrs[ptx][XT]['ref_pt']['contentType'] = "referenceInformation" IS2_atl11_tide_attrs[ptx][XT]['ref_pt']['long_name'] = ("fit center reference point number, " "segment_id") IS2_atl11_tide_attrs[ptx][XT]['ref_pt']['source'] = "derived, ATL11 algorithm" IS2_atl11_tide_attrs[ptx][XT]['ref_pt']['description'] = ("The reference-point number of the " "fit center for the datum track. The reference point is the 7 digit segment_id number " "corresponding to the center of the ATL06 data used for each ATL11 point. These are " "sequential, starting with 1 for the first segment after an ascending equatorial " "crossing node.") IS2_atl11_tide_attrs[ptx][XT]['ref_pt']['coordinates'] = \ "delta_time latitude longitude" #-- reference ground track of the crossing track IS2_atl11_tide[ptx][XT]['rgt'] = IS2_atl11_mds[ptx][XT]['rgt'].copy() IS2_atl11_fill[ptx][XT]['rgt'] = IS2_atl11_attrs[ptx][XT]['rgt']['_FillValue'] IS2_atl11_dims[ptx][XT]['rgt'] = None IS2_atl11_tide_attrs[ptx][XT]['rgt'] = collections.OrderedDict() IS2_atl11_tide_attrs[ptx][XT]['rgt']['units'] = "1" IS2_atl11_tide_attrs[ptx][XT]['rgt']['contentType'] = "referenceInformation" IS2_atl11_tide_attrs[ptx][XT]['rgt']['long_name'] = "crossover reference ground track" IS2_atl11_tide_attrs[ptx][XT]['rgt']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx][XT]['rgt']['description'] = "The RGT number for the crossing data." IS2_atl11_tide_attrs[ptx][XT]['rgt']['coordinates'] = \ "ref_pt delta_time latitude longitude" #-- cycle_number of the crossing track IS2_atl11_tide[ptx][XT]['cycle_number'] = IS2_atl11_mds[ptx][XT]['cycle_number'].copy() IS2_atl11_fill[ptx][XT]['cycle_number'] = IS2_atl11_attrs[ptx][XT]['cycle_number']['_FillValue'] IS2_atl11_dims[ptx][XT]['cycle_number'] = None IS2_atl11_tide_attrs[ptx][XT]['cycle_number'] = collections.OrderedDict() IS2_atl11_tide_attrs[ptx][XT]['cycle_number']['units'] = "1" IS2_atl11_tide_attrs[ptx][XT]['cycle_number']['long_name'] = "crossover cycle number" IS2_atl11_tide_attrs[ptx][XT]['cycle_number']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx][XT]['cycle_number']['description'] = ("Cycle number for the " "crossing data. Number of 91-day periods that have elapsed since ICESat-2 entered " "the science orbit. Each of the 1,387 reference ground track (RGTs) is targeted " "in the polar regions once every 91 days.") #-- delta time of the crossing track IS2_atl11_tide[ptx][XT]['delta_time'] = delta_time['XT'].copy() IS2_atl11_fill[ptx][XT]['delta_time'] = delta_time['XT'].fill_value IS2_atl11_dims[ptx][XT]['delta_time'] = ['ref_pt'] IS2_atl11_tide_attrs[ptx][XT]['delta_time'] = {} IS2_atl11_tide_attrs[ptx][XT]['delta_time']['units'] = "seconds since 2018-01-01" IS2_atl11_tide_attrs[ptx][XT]['delta_time']['long_name'] = "Elapsed GPS seconds" IS2_atl11_tide_attrs[ptx][XT]['delta_time']['standard_name'] = "time" IS2_atl11_tide_attrs[ptx][XT]['delta_time']['calendar'] = "standard" IS2_atl11_tide_attrs[ptx][XT]['delta_time']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx][XT]['delta_time']['description'] = ("Number of GPS " "seconds since the ATLAS SDP epoch. The ATLAS Standard Data Products (SDP) epoch offset " "is defined within /ancillary_data/atlas_sdp_gps_epoch as the number of GPS seconds " "between the GPS epoch (1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP epoch. By " "adding the offset contained within atlas_sdp_gps_epoch to delta time parameters, the " "time in gps_seconds relative to the GPS epoch can be computed.") IS2_atl11_tide_attrs[ptx]['delta_time']['coordinates'] = \ "ref_pt latitude longitude" #-- latitude of the crossover measurement IS2_atl11_tide[ptx][XT]['latitude'] = latitude['XT'].copy() IS2_atl11_fill[ptx][XT]['latitude'] = latitude['XT'].fill_value IS2_atl11_dims[ptx][XT]['latitude'] = ['ref_pt'] IS2_atl11_tide_attrs[ptx][XT]['latitude'] = collections.OrderedDict() IS2_atl11_tide_attrs[ptx][XT]['latitude']['units'] = "degrees_north" IS2_atl11_tide_attrs[ptx][XT]['latitude']['contentType'] = "physicalMeasurement" IS2_atl11_tide_attrs[ptx][XT]['latitude']['long_name'] = "crossover latitude" IS2_atl11_tide_attrs[ptx][XT]['latitude']['standard_name'] = "latitude" IS2_atl11_tide_attrs[ptx][XT]['latitude']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx][XT]['latitude']['description'] = ("Center latitude of " "selected segments") IS2_atl11_tide_attrs[ptx][XT]['latitude']['valid_min'] = -90.0 IS2_atl11_tide_attrs[ptx][XT]['latitude']['valid_max'] = 90.0 IS2_atl11_tide_attrs[ptx][XT]['latitude']['coordinates'] = \ "ref_pt delta_time longitude" #-- longitude of the crossover measurement IS2_atl11_tide[ptx][XT]['longitude'] = longitude['XT'].copy() IS2_atl11_fill[ptx][XT]['longitude'] = longitude['XT'].fill_value IS2_atl11_dims[ptx][XT]['longitude'] = ['ref_pt'] IS2_atl11_tide_attrs[ptx][XT]['longitude'] = collections.OrderedDict() IS2_atl11_tide_attrs[ptx][XT]['longitude']['units'] = "degrees_east" IS2_atl11_tide_attrs[ptx][XT]['longitude']['contentType'] = "physicalMeasurement" IS2_atl11_tide_attrs[ptx][XT]['longitude']['long_name'] = "crossover longitude" IS2_atl11_tide_attrs[ptx][XT]['longitude']['standard_name'] = "longitude" IS2_atl11_tide_attrs[ptx][XT]['longitude']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx][XT]['longitude']['description'] = ("Center longitude of " "selected segments") IS2_atl11_tide_attrs[ptx][XT]['longitude']['valid_min'] = -180.0 IS2_atl11_tide_attrs[ptx][XT]['longitude']['valid_max'] = 180.0 IS2_atl11_tide_attrs[ptx][XT]['longitude']['coordinates'] = \ "ref_pt delta_time latitude" #-- computed long-period equilibrium tide for the crossover measurement IS2_atl11_tide[ptx][XT]['tide_equilibrium'] = tide_lpe['XT'].copy() IS2_atl11_fill[ptx][XT]['tide_equilibrium'] = tide_lpe['XT'].fill_value IS2_atl11_dims[ptx][XT]['tide_equilibrium'] = ['ref_pt'] IS2_atl11_tide_attrs[ptx][XT]['tide_equilibrium'] = collections.OrderedDict() IS2_atl11_tide_attrs[ptx][XT]['tide_equilibrium']['units'] = "meters" IS2_atl11_tide_attrs[ptx][XT]['tide_equilibrium']['contentType'] = "referenceInformation" IS2_atl11_tide_attrs[ptx][XT]['tide_equilibrium']['long_name'] = \ "Long Period Equilibrium Tide" IS2_atl11_tide_attrs[ptx][XT]['tide_equilibrium']['description'] = ("Long-period " "equilibrium tidal elevation from the summation of fifteen tidal spectral lines") IS2_atl11_tide_attrs[ptx][XT]['tide_equilibrium']['reference'] = \ "https://doi.org/10.1111/j.1365-246X.1973.tb03420.x" IS2_atl11_tide_attrs[ptx][XT]['tide_equilibrium']['coordinates'] = \ "ref_pt delta_time latitude longitude" #-- print file information logger.info('\t{0}'.format(OUTPUT_FILE)) HDF5_ATL11_tide_write(IS2_atl11_tide, IS2_atl11_tide_attrs, CLOBBER=True, INPUT=os.path.basename(INPUT_FILE), FILL_VALUE=IS2_atl11_fill, DIMENSIONS=IS2_atl11_dims, FILENAME=os.path.join(DIRECTORY,OUTPUT_FILE)) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY,OUTPUT_FILE), MODE)
def compute_tide_corrections(x, y, delta_time, DIRECTORY=None, MODEL=None, ATLAS_FORMAT='netcdf', GZIP=False, DEFINITION_FILE=None, EPSG=3031, EPOCH=(2000, 1, 1, 0, 0, 0), TYPE='drift', TIME='UTC', METHOD='spline', EXTRAPOLATE=False, CUTOFF=10.0, FILL_VALUE=np.nan): """ Compute tides at points and times using tidal harmonics Parameters ---------- x: float x-coordinates in projection EPSG y: float y-coordinates in projection EPSG delta_time: float seconds since EPOCH or datetime array DIRECTORY: str or NoneType, default None working data directory for tide models MODEL: str or NoneType, default None Tide model to use in correction ATLAS_FORMAT: str, default 'netcdf' ATLAS tide model format (OTIS, netcdf) ATLAS tide model format - ``'OTIS'`` - ``'netcdf'`` GZIP: bool, default False Tide model files are gzip compressed DEFINITION_FILE: str or NoneType, default None Tide model definition file for use EPSG: int, default: 3031 (Polar Stereographic South, WGS84) Input coordinate system EPOCH: tuple, default (2000,1,1,0,0,0) Time period for calculating delta times TYPE: str or NoneType, default 'drift' Input data type - ``None``: determined from input variable dimensions - ``'drift'``: drift buoys or satellite/airborne altimetry - ``'grid'``: spatial grids or images - ``'time series'``: time series at a single point TIME: str, default 'UTC' Time type if need to compute leap seconds to convert to UTC - ``'GPS'``: leap seconds needed - ``'LORAN'``: leap seconds needed (LORAN = GPS + 9 seconds) - ``'TAI'``: leap seconds needed (TAI = GPS + 19 seconds) - ``'UTC'``: no leap seconds needed - ``'datetime'``: numpy datatime array in UTC METHOD: str Interpolation method - ```bilinear```: quick bilinear interpolation - ```spline```: scipy bivariate spline interpolation - ```linear```, ```nearest```: scipy regular grid interpolations EXTRAPOLATE: bool, default False Extrapolate with nearest-neighbors CUTOFF: float, default 10.0 Extrapolation cutoff in kilometers Set to np.inf to extrapolate for all points FILL_VALUE: float, default np.nan Output invalid value Returns ------- tide: float tidal elevation at coordinates and time in meters """ #-- check that tide directory is accessible try: os.access(DIRECTORY, os.F_OK) except: raise FileNotFoundError("Invalid tide directory") #-- get parameters for tide model if DEFINITION_FILE is not None: model = pyTMD.model(DIRECTORY).from_file(DEFINITION_FILE) else: model = pyTMD.model(DIRECTORY, format=ATLAS_FORMAT, compressed=GZIP).elevation(MODEL) #-- determine input data type based on variable dimensions if not TYPE: TYPE = pyTMD.spatial.data_type(x, y, delta_time) #-- reform coordinate dimensions for input grids #-- or verify coordinate dimension shapes if (TYPE.lower() == 'grid') and (np.size(x) != np.size(y)): x, y = np.meshgrid(np.copy(x), np.copy(y)) elif (TYPE.lower() == 'grid'): x = np.atleast_2d(x) y = np.atleast_2d(y) elif TYPE.lower() in ('time series', 'drift'): x = np.atleast_1d(x) y = np.atleast_1d(y) #-- converting x,y from EPSG to latitude/longitude try: #-- EPSG projection code string or int crs1 = pyproj.CRS.from_string("epsg:{0:d}".format(int(EPSG))) except (ValueError, pyproj.exceptions.CRSError): #-- Projection SRS string crs1 = pyproj.CRS.from_string(EPSG) crs2 = pyproj.CRS.from_string("epsg:{0:d}".format(4326)) transformer = pyproj.Transformer.from_crs(crs1, crs2, always_xy=True) lon, lat = transformer.transform(x.flatten(), y.flatten()) #-- assert delta time is an array delta_time = np.atleast_1d(delta_time) #-- calculate leap seconds if specified if (TIME.upper() == 'GPS'): GPS_Epoch_Time = pyTMD.time.convert_delta_time(0, epoch1=EPOCH, epoch2=(1980, 1, 6, 0, 0, 0), scale=1.0) GPS_Time = pyTMD.time.convert_delta_time(delta_time, epoch1=EPOCH, epoch2=(1980, 1, 6, 0, 0, 0), scale=1.0) #-- calculate difference in leap seconds from start of epoch leap_seconds = pyTMD.time.count_leap_seconds(GPS_Time) - \ pyTMD.time.count_leap_seconds(np.atleast_1d(GPS_Epoch_Time)) elif (TIME.upper() == 'LORAN'): #-- LORAN time is ahead of GPS time by 9 seconds GPS_Epoch_Time = pyTMD.time.convert_delta_time(-9.0, epoch1=EPOCH, epoch2=(1980, 1, 6, 0, 0, 0), scale=1.0) GPS_Time = pyTMD.time.convert_delta_time(delta_time - 9.0, epoch1=EPOCH, epoch2=(1980, 1, 6, 0, 0, 0), scale=1.0) #-- calculate difference in leap seconds from start of epoch leap_seconds = pyTMD.time.count_leap_seconds(GPS_Time) - \ pyTMD.time.count_leap_seconds(np.atleast_1d(GPS_Epoch_Time)) elif (TIME.upper() == 'TAI'): #-- TAI time is ahead of GPS time by 19 seconds GPS_Epoch_Time = pyTMD.time.convert_delta_time(-19.0, epoch1=EPOCH, epoch2=(1980, 1, 6, 0, 0, 0), scale=1.0) GPS_Time = pyTMD.time.convert_delta_time(delta_time - 19.0, epoch1=EPOCH, epoch2=(1980, 1, 6, 0, 0, 0), scale=1.0) #-- calculate difference in leap seconds from start of epoch leap_seconds = pyTMD.time.count_leap_seconds(GPS_Time) - \ pyTMD.time.count_leap_seconds(np.atleast_1d(GPS_Epoch_Time)) else: leap_seconds = 0.0 #-- convert delta times or datetimes objects if (TIME.lower() == 'datetime'): #-- convert delta time array from datetime object #-- to days relative to 1992-01-01T00:00:00 t = pyTMD.time.convert_datetime(delta_time, epoch=(1992, 1, 1, 0, 0, 0)) / 86400.0 else: #-- convert time to days relative to Jan 1, 1992 (48622mjd) t = pyTMD.time.convert_delta_time(delta_time - leap_seconds, epoch1=EPOCH, epoch2=(1992, 1, 1, 0, 0, 0), scale=(1.0 / 86400.0)) #-- delta time (TT - UT1) file delta_file = pyTMD.utilities.get_data_path(['data', 'merged_deltat.data']) #-- read tidal constants and interpolate to grid points if model.format in ('OTIS', 'ATLAS'): amp, ph, D, c = extract_tidal_constants(lon, lat, model.grid_file, model.model_file, model.projection, TYPE=model.type, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, GRID=model.format) deltat = np.zeros_like(t) elif (model.format == 'netcdf'): amp, ph, D, c = extract_netcdf_constants(lon, lat, model.grid_file, model.model_file, TYPE=model.type, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) deltat = np.zeros_like(t) elif (model.format == 'GOT'): amp, ph, c = extract_GOT_constants(lon, lat, model.model_file, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, t) elif (model.format == 'FES'): amp, ph = extract_FES_constants(lon, lat, model.model_file, TYPE=model.type, VERSION=model.version, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) #-- available model constituents c = model.constituents #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, t) #-- calculate complex phase in radians for Euler's cph = -1j * ph * np.pi / 180.0 #-- calculate constituent oscillation hc = amp * np.exp(cph) #-- predict tidal elevations at time and infer minor corrections if (TYPE.lower() == 'grid'): ny, nx = np.shape(x) nt = len(t) tide = np.ma.zeros((ny, nx, nt), fill_value=FILL_VALUE) tide.mask = np.zeros((ny, nx, nt), dtype=bool) for i in range(nt): TIDE = predict_tide(t[i], hc, c, DELTAT=deltat[i], CORRECTIONS=model.format) MINOR = infer_minor_corrections(t[i], hc, c, DELTAT=deltat[i], CORRECTIONS=model.format) #-- add major and minor components and reform grid tide[:, :, i] = np.reshape((TIDE + MINOR), (ny, nx)) tide.mask[:, :, i] = np.reshape((TIDE.mask | MINOR.mask), (ny, nx)) elif (TYPE.lower() == 'drift'): npts = len(t) tide = np.ma.zeros((npts), fill_value=FILL_VALUE) tide.mask = np.any(hc.mask, axis=1) tide.data[:] = predict_tide_drift(t, hc, c, DELTAT=deltat, CORRECTIONS=model.format) minor = infer_minor_corrections(t, hc, c, DELTAT=deltat, CORRECTIONS=model.format) tide.data[:] += minor.data[:] elif (TYPE.lower() == 'time series'): npts = len(t) tide = np.ma.zeros((npts), fill_value=FILL_VALUE) tide.mask = np.any(hc.mask, axis=1) tide.data[:] = predict_tidal_ts(t, hc, c, DELTAT=deltat, CORRECTIONS=model.format) minor = infer_minor_corrections(t, hc, c, DELTAT=deltat, CORRECTIONS=model.format) tide.data[:] += minor.data[:] #-- replace invalid values with fill value tide.data[tide.mask] = tide.fill_value #-- return the tide correction return tide
def compute_LPET_ICESat2(INPUT_FILE, VERBOSE=False, MODE=0o775): #-- create logger for verbosity level loglevel = logging.INFO if VERBOSE else logging.CRITICAL logger = pyTMD.utilities.build_logger('pytmd', level=loglevel) #-- read data from input file logger.info('{0} -->'.format(INPUT_FILE)) IS2_atl10_mds, IS2_atl10_attrs, IS2_atl10_beams = read_HDF5_ATL10( INPUT_FILE, ATTRIBUTES=True) DIRECTORY = os.path.dirname(INPUT_FILE) #-- extract parameters from ICESat-2 ATLAS HDF5 sea ice file name rx = re.compile( r'(processed_)?(ATL\d{2})-(\d{2})_(\d{4})(\d{2})(\d{2})' r'(\d{2})(\d{2})(\d{2})_(\d{4})(\d{2})(\d{2})_(\d{3})_(\d{2})(.*?).h5$' ) try: SUB, PRD, HEM, YY, MM, DD, HH, MN, SS, TRK, CYCL, SN, RL, VERS, AUX = rx.findall( INPUT_FILE).pop() except: #-- output long-period equilibrium tide HDF5 file (generic) fileBasename, fileExtension = os.path.splitext(INPUT_FILE) OUTPUT_FILE = '{0}_{1}{2}'.format(fileBasename, 'LPET', fileExtension) else: #-- output long-period equilibrium tide HDF5 file for ASAS/NSIDC granules args = (PRD, HEM, YY, MM, DD, HH, MN, SS, TRK, CYCL, SN, RL, VERS, AUX) file_format = '{0}-{1}_LPET_{2}{3}{4}{5}{6}{7}_{8}{9}{10}_{11}_{12}{13}.h5' OUTPUT_FILE = file_format.format(*args) #-- number of GPS seconds between the GPS epoch #-- and ATLAS Standard Data Product (SDP) epoch atlas_sdp_gps_epoch = IS2_atl10_mds['ancillary_data'][ 'atlas_sdp_gps_epoch'] #-- copy variables for outputting to HDF5 file IS2_atl10_tide = {} IS2_atl10_fill = {} IS2_atl10_dims = {} IS2_atl10_tide_attrs = {} #-- number of GPS seconds between the GPS epoch (1980-01-06T00:00:00Z UTC) #-- and ATLAS Standard Data Product (SDP) epoch (2018-01-01T00:00:00Z UTC) #-- Add this value to delta time parameters to compute full gps_seconds IS2_atl10_tide['ancillary_data'] = {} IS2_atl10_tide_attrs['ancillary_data'] = {} for key in ['atlas_sdp_gps_epoch']: #-- get each HDF5 variable IS2_atl10_tide['ancillary_data'][key] = IS2_atl10_mds[ 'ancillary_data'][key] #-- Getting attributes of group and included variables IS2_atl10_tide_attrs['ancillary_data'][key] = {} for att_name, att_val in IS2_atl10_attrs['ancillary_data'][key].items( ): IS2_atl10_tide_attrs['ancillary_data'][key][att_name] = att_val for gtx in sorted(IS2_atl10_beams): #-- output data dictionaries for beam IS2_atl10_tide[gtx] = dict(freeboard_beam_segment={}, leads={}) IS2_atl10_fill[gtx] = dict(freeboard_beam_segment={}, leads={}) IS2_atl10_dims[gtx] = dict(freeboard_beam_segment={}, leads={}) IS2_atl10_tide_attrs[gtx] = dict(freeboard_beam_segment={}, leads={}) #-- group attributes for beam IS2_atl10_tide_attrs[gtx]['Description'] = IS2_atl10_attrs[gtx][ 'Description'] IS2_atl10_tide_attrs[gtx]['atlas_pce'] = IS2_atl10_attrs[gtx][ 'atlas_pce'] IS2_atl10_tide_attrs[gtx]['atlas_beam_type'] = IS2_atl10_attrs[gtx][ 'atlas_beam_type'] IS2_atl10_tide_attrs[gtx]['groundtrack_id'] = IS2_atl10_attrs[gtx][ 'groundtrack_id'] IS2_atl10_tide_attrs[gtx]['atmosphere_profile'] = IS2_atl10_attrs[gtx][ 'atmosphere_profile'] IS2_atl10_tide_attrs[gtx]['atlas_spot_number'] = IS2_atl10_attrs[gtx][ 'atlas_spot_number'] IS2_atl10_tide_attrs[gtx]['sc_orientation'] = IS2_atl10_attrs[gtx][ 'sc_orientation'] #-- group attributes for freeboard_beam_segment IS2_atl10_tide_attrs[gtx]['freeboard_beam_segment']['Description'] = ( "Contains freeboard " "estimate and associated height segment parameters for only the sea ice segments by beam." ) IS2_atl10_tide_attrs[gtx]['freeboard_beam_segment']['data_rate'] = ( "Data within this " "group are stored at the freeboard swath segment rate.") #-- group attributes for leads IS2_atl10_tide_attrs[gtx]['leads']['Description'] = ( "Contains parameters relating " "to the freeboard values.") IS2_atl10_tide_attrs[gtx]['leads']['data_rate'] = ( "Data within this " "group are stored at the lead index rate.") #-- for each ATL10 group for group in ['freeboard_beam_segment', 'leads']: #-- number of segments val = IS2_atl10_mds[gtx][group] n_seg = len(val['delta_time']) #-- convert time from ATLAS SDP to days relative to Jan 1, 1992 gps_seconds = atlas_sdp_gps_epoch + val['delta_time'] leap_seconds = pyTMD.time.count_leap_seconds(gps_seconds) tide_time = pyTMD.time.convert_delta_time( gps_seconds - leap_seconds, epoch1=(1980, 1, 6, 0, 0, 0), epoch2=(1992, 1, 1, 0, 0, 0), scale=1.0 / 86400.0) #-- interpolate delta times from calendar dates to tide time delta_file = pyTMD.utilities.get_data_path( ['data', 'merged_deltat.data']) deltat = calc_delta_time(delta_file, tide_time) #-- predict long-period equilibrium tides at latitudes and time tide_lpe = compute_equilibrium_tide(tide_time + deltat, val['latitude']) #-- delta time IS2_atl10_tide[gtx][group]['delta_time'] = val['delta_time'].copy() IS2_atl10_fill[gtx][group]['delta_time'] = None IS2_atl10_dims[gtx][group]['delta_time'] = None IS2_atl10_tide_attrs[gtx][group]['delta_time'] = {} IS2_atl10_tide_attrs[gtx][group]['delta_time'][ 'units'] = "seconds since 2018-01-01" IS2_atl10_tide_attrs[gtx][group]['delta_time'][ 'long_name'] = "Elapsed GPS seconds" IS2_atl10_tide_attrs[gtx][group]['delta_time'][ 'standard_name'] = "time" IS2_atl10_tide_attrs[gtx][group]['delta_time'][ 'source'] = "telemetry" IS2_atl10_tide_attrs[gtx][group]['delta_time'][ 'calendar'] = "standard" IS2_atl10_tide_attrs[gtx][group]['delta_time']['description'] = ( "Number of " "GPS seconds since the ATLAS SDP epoch. The ATLAS Standard Data Products (SDP) epoch " "offset is defined within /ancillary_data/atlas_sdp_gps_epoch as the number of GPS " "seconds between the GPS epoch (1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP " "epoch. By adding the offset contained within atlas_sdp_gps_epoch to delta time " "parameters, the time in gps_seconds relative to the GPS epoch can be computed." ) IS2_atl10_tide_attrs[gtx][group]['delta_time']['coordinates'] = \ "latitude longitude" #-- latitude IS2_atl10_tide[gtx][group]['latitude'] = val['latitude'].copy() IS2_atl10_fill[gtx][group]['latitude'] = None IS2_atl10_dims[gtx][group]['latitude'] = ['delta_time'] IS2_atl10_tide_attrs[gtx][group]['latitude'] = {} IS2_atl10_tide_attrs[gtx][group]['latitude'][ 'units'] = "degrees_north" IS2_atl10_tide_attrs[gtx][group]['latitude'][ 'contentType'] = "physicalMeasurement" IS2_atl10_tide_attrs[gtx][group]['latitude'][ 'long_name'] = "Latitude" IS2_atl10_tide_attrs[gtx][group]['latitude'][ 'standard_name'] = "latitude" IS2_atl10_tide_attrs[gtx][group]['latitude']['description'] = ( "Latitude of " "segment center") IS2_atl10_tide_attrs[gtx][group]['latitude']['valid_min'] = -90.0 IS2_atl10_tide_attrs[gtx][group]['latitude']['valid_max'] = 90.0 IS2_atl10_tide_attrs[gtx][group]['latitude']['coordinates'] = \ "delta_time longitude" #-- longitude IS2_atl10_tide[gtx][group]['longitude'] = val['longitude'].copy() IS2_atl10_fill[gtx][group]['longitude'] = None IS2_atl10_dims[gtx][group]['longitude'] = ['delta_time'] IS2_atl10_tide_attrs[gtx][group]['longitude'] = {} IS2_atl10_tide_attrs[gtx][group]['longitude'][ 'units'] = "degrees_east" IS2_atl10_tide_attrs[gtx][group]['longitude'][ 'contentType'] = "physicalMeasurement" IS2_atl10_tide_attrs[gtx][group]['longitude'][ 'long_name'] = "Longitude" IS2_atl10_tide_attrs[gtx][group]['longitude'][ 'standard_name'] = "longitude" IS2_atl10_tide_attrs[gtx][group]['longitude']['description'] = ( "Longitude of " "segment center") IS2_atl10_tide_attrs[gtx][group]['longitude']['valid_min'] = -180.0 IS2_atl10_tide_attrs[gtx][group]['longitude']['valid_max'] = 180.0 IS2_atl10_tide_attrs[gtx][group]['longitude']['coordinates'] = \ "delta_time latitude" #-- geophysical variables IS2_atl10_tide[gtx][group]['geophysical'] = {} IS2_atl10_fill[gtx][group]['geophysical'] = {} IS2_atl10_dims[gtx][group]['geophysical'] = {} IS2_atl10_tide_attrs[gtx][group]['geophysical'] = {} IS2_atl10_tide_attrs[gtx][group]['geophysical']['Description'] = ( "Contains geophysical " "parameters and corrections used to correct photon heights for geophysical " "effects, such as tides.") IS2_atl10_tide_attrs[gtx][group]['geophysical']['data_rate'] = ( "Data within this group " "are stored at the variable segment rate.") #-- computed long-period equilibrium tide IS2_atl10_tide[gtx][group]['geophysical'][ 'height_segment_lpe'] = tide_lpe IS2_atl10_fill[gtx][group]['geophysical'][ 'height_segment_lpe'] = None IS2_atl10_dims[gtx][group]['geophysical']['height_segment_lpe'] = [ 'delta_time' ] IS2_atl10_tide_attrs[gtx][group]['geophysical'][ 'height_segment_lpe'] = {} IS2_atl10_tide_attrs[gtx][group]['geophysical'][ 'height_segment_lpe']['units'] = "meters" IS2_atl10_tide_attrs[gtx][group]['geophysical']['height_segment_lpe']['contentType'] = \ "referenceInformation" IS2_atl10_tide_attrs[gtx][group]['geophysical']['height_segment_lpe']['long_name'] = \ "Long Period Equilibrium Tide" IS2_atl10_tide_attrs[gtx][group]['geophysical'][ 'height_segment_lpe']['description'] = ( "Long-period " "equilibrium tidal elevation from the summation of fifteen tidal spectral lines" ) IS2_atl10_tide_attrs[gtx][group]['geophysical']['height_segment_lpe']['reference'] = \ "https://doi.org/10.1111/j.1365-246X.1973.tb03420.x" IS2_atl10_tide_attrs[gtx][group]['geophysical']['height_segment_lpe']['coordinates'] = \ "../delta_time ../latitude ../longitude" #-- print file information logger.info('\t{0}'.format(OUTPUT_FILE)) HDF5_ATL10_tide_write(IS2_atl10_tide, IS2_atl10_tide_attrs, CLOBBER=True, INPUT=os.path.basename(INPUT_FILE), FILL_VALUE=IS2_atl10_fill, DIMENSIONS=IS2_atl10_dims, FILENAME=os.path.join(DIRECTORY, OUTPUT_FILE)) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY, OUTPUT_FILE), MODE)
def compute_LPET_elevations(input_file, output_file, FORMAT='csv', VARIABLES=['time','lat','lon','data'], HEADER=0, TYPE='drift', TIME_UNITS='days since 1858-11-17T00:00:00', TIME=None, PROJECTION='4326', VERBOSE=False, MODE=0o775): #-- output netCDF4 and HDF5 file attributes #-- will be added to YAML header in csv files attrib = {} #-- latitude attrib['lat'] = {} attrib['lat']['long_name'] = 'Latitude' attrib['lat']['units'] = 'Degrees_North' #-- longitude attrib['lon'] = {} attrib['lon']['long_name'] = 'Longitude' attrib['lon']['units'] = 'Degrees_East' #-- long-period equilibrium tides attrib['tide_lpe'] = {} attrib['tide_lpe']['long_name'] = 'Equilibrium_Tide' attrib['tide_lpe']['description'] = ('Long-period_equilibrium_tidal_' 'elevation_from_the_summation_of_fifteen_tidal_spectral_lines') attrib['tide_lpe']['reference'] = ('https://doi.org/10.1111/' 'j.1365-246X.1973.tb03420.x') attrib['tide_lpe']['units'] = 'meters' #-- time attrib['time'] = {} attrib['time']['long_name'] = 'Time' attrib['time']['units'] = 'days since 1992-01-01T00:00:00' attrib['time']['calendar'] = 'standard' #-- read input file to extract time, spatial coordinates and data if (FORMAT == 'csv'): dinput = pyTMD.spatial.from_ascii(input_file, columns=VARIABLES, header=HEADER, verbose=VERBOSE) elif (FORMAT == 'netCDF4'): dinput = pyTMD.spatial.from_netCDF4(input_file, timename=VARIABLES[0], xname=VARIABLES[2], yname=VARIABLES[1], varname=VARIABLES[3], verbose=VERBOSE) elif (FORMAT == 'HDF5'): dinput = pyTMD.spatial.from_HDF5(input_file, timename=VARIABLES[0], xname=VARIABLES[2], yname=VARIABLES[1], varname=VARIABLES[3], verbose=VERBOSE) elif (FORMAT == 'geotiff'): dinput = pyTMD.spatial.from_geotiff(input_file, verbose=VERBOSE) #-- copy global geotiff attributes for projection and grid parameters for att_name in ['projection','wkt','spacing','extent']: attrib[att_name] = dinput['attributes'][att_name] #-- update time variable if entered as argument if TIME is not None: dinput['time'] = np.copy(TIME) #-- converting x,y from projection to latitude/longitude #-- could try to extract projection attributes from netCDF4 and HDF5 files try: crs1 = pyproj.CRS.from_string("epsg:{0:d}".format(int(PROJECTION))) except (ValueError,pyproj.exceptions.CRSError): crs1 = pyproj.CRS.from_string(PROJECTION) crs2 = pyproj.CRS.from_string("epsg:{0:d}".format(4326)) transformer = pyproj.Transformer.from_crs(crs1, crs2, always_xy=True) if (TYPE == 'grid'): ny,nx = (len(dinput['y']),len(dinput['x'])) gridx,gridy = np.meshgrid(dinput['x'],dinput['y']) lon,lat = transformer.transform(gridx.flatten(),gridy.flatten()) elif (TYPE == 'drift'): lon,lat = transformer.transform(dinput['x'].flatten(), dinput['y'].flatten()) #-- extract time units from netCDF4 and HDF5 attributes or from TIME_UNITS try: time_string = dinput['attributes']['time']['units'] except (TypeError, KeyError): epoch1,to_secs = pyTMD.time.parse_date_string(TIME_UNITS) else: epoch1,to_secs = pyTMD.time.parse_date_string(time_string) #-- convert time from units to days since 1992-01-01T00:00:00 tide_time = pyTMD.time.convert_delta_time(to_secs*dinput['time'].flatten(), epoch1=epoch1, epoch2=(1992,1,1,0,0,0), scale=1.0/86400.0) #-- interpolate delta times from calendar dates to tide time delta_file = get_data_path(['data','merged_deltat.data']) deltat = calc_delta_time(delta_file, tide_time) #-- number of time points nt = len(tide_time) #-- predict long-period equilibrium tides at time if (TYPE == 'grid'): tide_lpe = np.zeros((ny,nx,nt)) for i in range(nt): lpet = compute_equilibrium_tide(tide_time[i] + deltat[i], lat) tide_lpe[:,:,i] = np.reshape(lpet,(ny,nx)) elif (TYPE == 'drift'): tide_lpe = compute_equilibrium_tide(tide_time + deltat, lat) #-- output to file output = dict(time=tide_time,lon=lon,lat=lat,tide_lpe=tide_lpe) if (FORMAT == 'csv'): pyTMD.spatial.to_ascii(output, attrib, output_file, delimiter=',', columns=['time','lat','lon','tide_lpe'], verbose=VERBOSE) elif (FORMAT == 'netCDF4'): pyTMD.spatial.to_netCDF4(output, attrib, output_file, verbose=VERBOSE) elif (FORMAT == 'HDF5'): pyTMD.spatial.to_HDF5(output, attrib, output_file, verbose=VERBOSE) elif (FORMAT == 'geotiff'): pyTMD.spatial.to_geotiff(output, attrib, output_file, verbose=VERBOSE, varname='tide_lpe') #-- change the permissions level to MODE os.chmod(output_file, MODE)
def compute_tidal_currents(tide_dir, input_file, output_file, TIDE_MODEL=None, FORMAT='csv', VARIABLES=['time','lat','lon','data'], HEADER=0, TYPE='drift', TIME_UNITS='days since 1858-11-17T00:00:00', TIME=None, PROJECTION='4326', METHOD='spline', EXTRAPOLATE=False, VERBOSE=False, MODE=0o775): #-- select between tide models if (TIDE_MODEL == 'CATS0201'): grid_file = os.path.join(tide_dir,'cats0201_tmd','grid_CATS') model_file = os.path.join(tide_dir,'cats0201_tmd','UV0_CATS02_01') reference = 'https://mail.esr.org/polar_tide_models/Model_CATS0201.html' model_format = 'OTIS' EPSG = '4326' TYPES = ['u','v'] elif (TIDE_MODEL == 'CATS2008'): grid_file = os.path.join(tide_dir,'CATS2008','grid_CATS2008') model_file = os.path.join(tide_dir,'CATS2008','uv.CATS2008.out') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') model_format = 'OTIS' EPSG = 'CATS2008' TYPES = ['u','v'] elif (TIDE_MODEL == 'TPXO9-atlas'): model_directory = os.path.join(tide_dir,'TPXO9_atlas') grid_file = 'grid_tpxo9_atlas.nc.gz' model_files = {} model_files['u'] = ['u_q1_tpxo9_atlas_30.nc.gz','u_o1_tpxo9_atlas_30.nc.gz', 'u_p1_tpxo9_atlas_30.nc.gz','u_k1_tpxo9_atlas_30.nc.gz', 'u_n2_tpxo9_atlas_30.nc.gz','u_m2_tpxo9_atlas_30.nc.gz', 'u_s2_tpxo9_atlas_30.nc.gz','u_k2_tpxo9_atlas_30.nc.gz', 'u_m4_tpxo9_atlas_30.nc.gz','u_ms4_tpxo9_atlas_30.nc.gz', 'u_mn4_tpxo9_atlas_30.nc.gz','u_2n2_tpxo9_atlas_30.nc.gz'] model_files['v'] = ['v_q1_tpxo9_atlas_30.nc.gz','v_o1_tpxo9_atlas_30.nc.gz', 'v_p1_tpxo9_atlas_30.nc.gz','v_k1_tpxo9_atlas_30.nc.gz', 'v_n2_tpxo9_atlas_30.nc.gz','v_m2_tpxo9_atlas_30.nc.gz', 'v_s2_tpxo9_atlas_30.nc.gz','v_k2_tpxo9_atlas_30.nc.gz', 'v_m4_tpxo9_atlas_30.nc.gz','v_ms4_tpxo9_atlas_30.nc.gz', 'v_mn4_tpxo9_atlas_30.nc.gz','v_2n2_tpxo9_atlas_30.nc.gz'] reference = 'http://volkov.oce.orst.edu/tides/tpxo9_atlas.html' model_format = 'netcdf' TYPES = ['u','v'] model_scale = 1.0/100.0 GZIP = True elif (TIDE_MODEL == 'TPXO9-atlas-v2'): model_directory = os.path.join(tide_dir,'TPXO9_atlas_v2') grid_file = 'grid_tpxo9_atlas_30_v2.nc.gz' model_files = {} model_files['u'] = ['u_q1_tpxo9_atlas_30_v2.nc.gz','u_o1_tpxo9_atlas_30_v2.nc.gz', 'u_p1_tpxo9_atlas_30_v2.nc.gz','u_k1_tpxo9_atlas_30_v2.nc.gz', 'u_n2_tpxo9_atlas_30_v2.nc.gz','u_m2_tpxo9_atlas_30_v2.nc.gz', 'u_s2_tpxo9_atlas_30_v2.nc.gz','u_k2_tpxo9_atlas_30_v2.nc.gz', 'u_m4_tpxo9_atlas_30_v2.nc.gz','u_ms4_tpxo9_atlas_30_v2.nc.gz', 'u_mn4_tpxo9_atlas_30_v2.nc.gz','u_2n2_tpxo9_atlas_30_v2.nc.gz'] model_files['v'] = ['v_q1_tpxo9_atlas_30_v2.nc.gz','v_o1_tpxo9_atlas_30_v2.nc.gz', 'v_p1_tpxo9_atlas_30_v2.nc.gz','v_k1_tpxo9_atlas_30_v2.nc.gz', 'v_n2_tpxo9_atlas_30_v2.nc.gz','v_m2_tpxo9_atlas_30_v2.nc.gz', 'v_s2_tpxo9_atlas_30_v2.nc.gz','v_k2_tpxo9_atlas_30_v2.nc.gz', 'v_m4_tpxo9_atlas_30_v2.nc.gz','v_ms4_tpxo9_atlas_30_v2.nc.gz', 'v_mn4_tpxo9_atlas_30_v2.nc.gz','v_2n2_tpxo9_atlas_30_v2.nc.gz'] reference = 'https://www.tpxo.net/global/tpxo9-atlas' model_format = 'netcdf' TYPES = ['u','v'] model_scale = 1.0/100.0 GZIP = True elif (TIDE_MODEL == 'TPXO9.1'): grid_file = os.path.join(tide_dir,'TPXO9.1','DATA','grid_tpxo9') model_file = os.path.join(tide_dir,'TPXO9.1','DATA','u_tpxo9.v1') reference = 'http://volkov.oce.orst.edu/tides/global.html' model_format = 'OTIS' EPSG = '4326' TYPES = ['u','v'] elif (TIDE_MODEL == 'TPXO8-atlas'): grid_file = os.path.join(tide_dir,'tpxo8_atlas','grid_tpxo8atlas_30_v1') model_file = os.path.join(tide_dir,'tpxo8_atlas','uv.tpxo8_atlas_30_v1') reference = 'http://volkov.oce.orst.edu/tides/tpxo8_atlas.html' model_format = 'ATLAS' EPSG = '4326' TYPES = ['u','v'] elif (TIDE_MODEL == 'TPXO7.2'): grid_file = os.path.join(tide_dir,'TPXO7.2_tmd','grid_tpxo7.2') model_file = os.path.join(tide_dir,'TPXO7.2_tmd','u_tpxo7.2') reference = 'http://volkov.oce.orst.edu/tides/global.html' model_format = 'OTIS' EPSG = '4326' TYPES = ['u','v'] elif (TIDE_MODEL == 'AODTM-5'): grid_file = os.path.join(tide_dir,'aodtm5_tmd','grid_Arc5km') model_file = os.path.join(tide_dir,'aodtm5_tmd','UV0_Arc5km') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aodtm-5/') model_format = 'OTIS' EPSG = 'PSNorth' TYPES = ['u','v'] elif (TIDE_MODEL == 'AOTIM-5'): grid_file = os.path.join(tide_dir,'aotim5_tmd','grid_Arc5km') model_file = os.path.join(tide_dir,'aotim5_tmd','UV_Arc5km') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') model_format = 'OTIS' EPSG = 'PSNorth' TYPES = ['u','v'] elif (TIDE_MODEL == 'AOTIM-5-2018'): grid_file = os.path.join(tide_dir,'Arc5km2018','grid_Arc5km2018') model_file = os.path.join(tide_dir,'Arc5km2018','UV_Arc5km2018') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') model_format = 'OTIS' EPSG = 'PSNorth' TYPES = ['u','v'] elif (TIDE_MODEL == 'FES2014'): model_directory = {} model_directory['u'] = os.path.join(tide_dir,'fes2014','eastward_velocity') model_directory['v'] = os.path.join(tide_dir,'fes2014','northward_velocity') model_files = ['2n2.nc.gz','eps2.nc.gz','j1.nc.gz','k1.nc.gz', 'k2.nc.gz','l2.nc.gz','la2.nc.gz','m2.nc.gz','m3.nc.gz','m4.nc.gz', 'm6.nc.gz','m8.nc.gz','mf.nc.gz','mks2.nc.gz','mm.nc.gz', 'mn4.nc.gz','ms4.nc.gz','msf.nc.gz','msqm.nc.gz','mtm.nc.gz', 'mu2.nc.gz','n2.nc.gz','n4.nc.gz','nu2.nc.gz','o1.nc.gz','p1.nc.gz', 'q1.nc.gz','r2.nc.gz','s1.nc.gz','s2.nc.gz','s4.nc.gz','sa.nc.gz', 'ssa.nc.gz','t2.nc.gz'] c = ['2n2','eps2','j1','k1','k2','l2','lambda2','m2','m3','m4','m6', 'm8','mf','mks2','mm','mn4','ms4','msf','msqm','mtm','mu2','n2', 'n4','nu2','o1','p1','q1','r2','s1','s2','s4','sa','ssa','t2'] reference = ('https://www.aviso.altimetry.fr/en/data/products' 'auxiliary-products/global-tide-fes.html') model_format = 'FES' TYPES = ['u','v'] model_scale = 1.0 #-- invalid value fill_value = -9999.0 #-- output netCDF4 and HDF5 file attributes #-- will be added to YAML header in csv files attrib = {} #-- latitude attrib['lat'] = {} attrib['lat']['long_name'] = 'Latitude' attrib['lat']['units'] = 'Degrees_North' #-- longitude attrib['lon'] = {} attrib['lon']['long_name'] = 'Longitude' attrib['lon']['units'] = 'Degrees_East' #-- zonal tidal currents attrib['u'] = {} attrib['u']['description'] = ('depth_averaged_tidal_zonal_current_' 'from_harmonic_constants') attrib['u']['model'] = TIDE_MODEL attrib['u']['units'] = 'cm/s' attrib['u']['long_name'] = 'zonal_tidal_current' attrib['u']['_FillValue'] = fill_value #-- meridional tidal currents attrib['v'] = {} attrib['v']['description'] = ('depth_averaged_tidal_meridional_current_' 'from_harmonic_constants') attrib['v']['model'] = TIDE_MODEL attrib['v']['units'] = 'cm/s' attrib['v']['long_name'] = 'meridional_tidal_current' attrib['v']['_FillValue'] = fill_value #-- time attrib['time'] = {} attrib['time']['long_name'] = 'Time' attrib['time']['units'] = 'days since 1992-01-01T00:00:00' attrib['time']['calendar'] = 'standard' #-- read input file to extract time, spatial coordinates and data if (FORMAT == 'csv'): dinput = pyTMD.spatial.from_ascii(input_file, columns=VARIABLES, header=HEADER, verbose=VERBOSE) elif (FORMAT == 'netCDF4'): dinput = pyTMD.spatial.from_netCDF4(input_file, timename=VARIABLES[0], xname=VARIABLES[2], yname=VARIABLES[1], varname=VARIABLES[3], verbose=VERBOSE) elif (FORMAT == 'HDF5'): dinput = pyTMD.spatial.from_HDF5(input_file, timename=VARIABLES[0], xname=VARIABLES[2], yname=VARIABLES[1], varname=VARIABLES[3], verbose=VERBOSE) elif (FORMAT == 'geotiff'): dinput = pyTMD.spatial.from_geotiff(input_file, verbose=VERBOSE) #-- copy global geotiff attributes for projection and grid parameters for att_name in ['projection','wkt','spacing','extent']: attrib[att_name] = dinput['attributes'][att_name] #-- update time variable if entered as argument if TIME is not None: dinput['time'] = np.copy(TIME) #-- converting x,y from projection to latitude/longitude #-- could try to extract projection attributes from netCDF4 and HDF5 files try: crs1 = pyproj.CRS.from_string("epsg:{0:d}".format(int(PROJECTION))) except (ValueError,pyproj.exceptions.CRSError): crs1 = pyproj.CRS.from_string(PROJECTION) crs2 = pyproj.CRS.from_string("epsg:{0:d}".format(4326)) transformer = pyproj.Transformer.from_crs(crs1, crs2, always_xy=True) if (TYPE == 'grid'): ny,nx = (len(dinput['y']),len(dinput['x'])) gridx,gridy = np.meshgrid(dinput['x'],dinput['y']) lon,lat = transformer.transform(gridx,gridy) elif (TYPE == 'drift'): lon,lat = transformer.transform(dinput['x'],dinput['y']) #-- extract time units from netCDF4 and HDF5 attributes or from TIME_UNITS try: time_string = dinput['attributes']['time']['units'] except (TypeError, KeyError): epoch1,to_secs = pyTMD.time.parse_date_string(TIME_UNITS) else: epoch1,to_secs = pyTMD.time.parse_date_string(time_string) #-- convert time from units to days since 1992-01-01T00:00:00 tide_time = pyTMD.time.convert_delta_time(to_secs*dinput['time'].flatten(), epoch1=epoch1, epoch2=(1992,1,1,0,0,0), scale=1.0/86400.0) #-- number of time points nt = len(tide_time) #-- python dictionary with output data output = {'time':tide_time,'lon':lon,'lat':lat} #-- iterate over u and v currents for t in TYPES: #-- read tidal constants and interpolate to grid points if model_format in ('OTIS','ATLAS'): amp,ph,D,c = extract_tidal_constants(lon.flatten(), lat.flatten(), grid_file, model_file, EPSG, TYPE=t, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, GRID=model_format) deltat = np.zeros((nt)) elif (model_format == 'netcdf'): amp,ph,D,c = extract_netcdf_constants(lon.flatten(), lat.flatten(), model_directory, grid_file, model_files[t], TYPE=t, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=model_scale, GZIP=GZIP) deltat = np.zeros((nt)) elif (model_format == 'FES'): amp,ph = extract_FES_constants(lon.flatten(), lat.flatten(), model_directory[t], model_files, TYPE=t, VERSION=TIDE_MODEL, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=model_scale) #-- interpolate delta times from calendar dates to tide time delta_file = get_data_path(['data','merged_deltat.data']) deltat = calc_delta_time(delta_file, tide_time) #-- calculate complex phase in radians for Euler's cph = -1j*ph*np.pi/180.0 #-- calculate constituent oscillation hc = amp*np.exp(cph) #-- predict tidal currents at time and infer minor corrections if (TYPE == 'grid'): output[t] = np.ma.zeros((ny,nx,nt),fill_value=fill_value) output[t].mask = np.zeros((ny,nx,nt),dtype=np.bool) for i in range(nt): TIDE = predict_tide(tide_time[i], hc, c, DELTAT=deltat[i], CORRECTIONS=model_format) MINOR = infer_minor_corrections(tide_time[i], hc, c, DELTAT=deltat[i], CORRECTIONS=model_format) #-- add major and minor components and reform grid output[t][:,:,i] = np.reshape((TIDE+MINOR), (ny,nx)) output[t].mask[:,:,i] = np.reshape((TIDE.mask | MINOR.mask), (ny,nx)) elif (TYPE == 'drift'): output[t] = np.ma.zeros((nt), fill_value=fill_value) output[t].mask = np.any(hc.mask,axis=1) output[t].data[:] = predict_tide_drift(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model_format) minor = infer_minor_corrections(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model_format) output[t].data[:] += minor.data[:] #-- replace invalid values with fill value output[t].data[output[t].mask] = output[t].fill_value #-- output to file if (FORMAT == 'csv'): pyTMD.spatial.to_ascii(output, attrib, output_file, delimiter=',', columns=['time','lat','lon','u','v'], verbose=VERBOSE) elif (FORMAT == 'netCDF4'): pyTMD.spatial.to_netCDF4(output, attrib, output_file, verbose=VERBOSE) elif (FORMAT == 'HDF5'): pyTMD.spatial.to_HDF5(output, attrib, output_file, verbose=VERBOSE) elif (FORMAT == 'geotiff'): #-- merge current variables into a single variable output['data'] = np.concatenate((output['u'],output['v']),axis=-1) attrib['data'] = {'_FillValue':fill_value} pyTMD.spatial.to_geotiff(output, attrib, output_file, verbose=VERBOSE, varname='data') #-- change the permissions level to MODE os.chmod(output_file, MODE)
def compute_tides_ICESat2(tide_dir, INPUT_FILE, TIDE_MODEL=None, ATLAS_FORMAT=None, GZIP=True, DEFINITION_FILE=None, METHOD='spline', EXTRAPOLATE=False, CUTOFF=None, VERBOSE=False, MODE=0o775): #-- create logger for verbosity level loglevel = logging.INFO if VERBOSE else logging.CRITICAL logger = pyTMD.utilities.build_logger('pytmd', level=loglevel) #-- get parameters for tide model if DEFINITION_FILE is not None: model = pyTMD.model(tide_dir).from_file(DEFINITION_FILE) else: model = pyTMD.model(tide_dir, format=ATLAS_FORMAT, compressed=GZIP).elevation(TIDE_MODEL) #-- read data from input file logger.info('{0} -->'.format(INPUT_FILE)) IS2_atl03_mds, IS2_atl03_attrs, IS2_atl03_beams = read_HDF5_ATL03_main( INPUT_FILE, ATTRIBUTES=True) DIRECTORY = os.path.dirname(INPUT_FILE) #-- extract parameters from ICESat-2 ATLAS HDF5 file name rx = re.compile( r'(processed_)?(ATL\d{2})_(\d{4})(\d{2})(\d{2})(\d{2})' r'(\d{2})(\d{2})_(\d{4})(\d{2})(\d{2})_(\d{3})_(\d{2})(.*?).h5$') try: SUB, PRD, YY, MM, DD, HH, MN, SS, TRK, CYCL, GRAN, RL, VERS, AUX = rx.findall( INPUT_FILE).pop() except: #-- output tide HDF5 file (generic) fileBasename, fileExtension = os.path.splitext(INPUT_FILE) args = (fileBasename, model.name, fileExtension) OUTPUT_FILE = '{0}_{1}_TIDES{2}'.format(*args) else: #-- output tide HDF5 file for ASAS/NSIDC granules args = (PRD, model.name, YY, MM, DD, HH, MN, SS, TRK, CYCL, GRAN, RL, VERS, AUX) file_format = '{0}_{1}_TIDES_{2}{3}{4}{5}{6}{7}_{8}{9}{10}_{11}_{12}{13}.h5' OUTPUT_FILE = file_format.format(*args) #-- number of GPS seconds between the GPS epoch #-- and ATLAS Standard Data Product (SDP) epoch atlas_sdp_gps_epoch = IS2_atl03_mds['ancillary_data'][ 'atlas_sdp_gps_epoch'] #-- delta time (TT - UT1) file delta_file = pyTMD.utilities.get_data_path(['data', 'merged_deltat.data']) #-- copy variables for outputting to HDF5 file IS2_atl03_tide = {} IS2_atl03_fill = {} IS2_atl03_dims = {} IS2_atl03_tide_attrs = {} #-- number of GPS seconds between the GPS epoch (1980-01-06T00:00:00Z UTC) #-- and ATLAS Standard Data Product (SDP) epoch (2018-01-01T00:00:00Z UTC) #-- Add this value to delta time parameters to compute full gps_seconds IS2_atl03_tide['ancillary_data'] = {} IS2_atl03_tide_attrs['ancillary_data'] = {} for key in ['atlas_sdp_gps_epoch']: #-- get each HDF5 variable IS2_atl03_tide['ancillary_data'][key] = IS2_atl03_mds[ 'ancillary_data'][key] #-- Getting attributes of group and included variables IS2_atl03_tide_attrs['ancillary_data'][key] = {} for att_name, att_val in IS2_atl03_attrs['ancillary_data'][key].items( ): IS2_atl03_tide_attrs['ancillary_data'][key][att_name] = att_val #-- for each input beam within the file for gtx in sorted(IS2_atl03_beams): #-- output data dictionaries for beam IS2_atl03_tide[gtx] = dict(geolocation={}, geophys_corr={}) IS2_atl03_fill[gtx] = dict(geolocation={}, geophys_corr={}) IS2_atl03_dims[gtx] = dict(geolocation={}, geophys_corr={}) IS2_atl03_tide_attrs[gtx] = dict(geolocation={}, geophys_corr={}) #-- read data and attributes for beam val, attrs = read_HDF5_ATL03_beam(INPUT_FILE, gtx, ATTRIBUTES=True) #-- number of segments n_seg = len(val['geolocation']['segment_id']) #-- extract variables for computing tides segment_id = val['geolocation']['segment_id'].copy() delta_time = val['geolocation']['delta_time'].copy() lon = val['geolocation']['reference_photon_lon'].copy() lat = val['geolocation']['reference_photon_lat'].copy() #-- invalid value fv = attrs['geolocation']['sigma_h']['_FillValue'] #-- convert time from ATLAS SDP to days relative to Jan 1, 1992 gps_seconds = atlas_sdp_gps_epoch + delta_time leap_seconds = pyTMD.time.count_leap_seconds(gps_seconds) tide_time = pyTMD.time.convert_delta_time(gps_seconds - leap_seconds, epoch1=(1980, 1, 6, 0, 0, 0), epoch2=(1992, 1, 1, 0, 0, 0), scale=1.0 / 86400.0) #-- read tidal constants and interpolate to grid points if model.format in ('OTIS', 'ATLAS'): amp, ph, D, c = extract_tidal_constants(lon, lat, model.grid_file, model.model_file, model.projection, TYPE=model.type, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, GRID=model.format) deltat = np.zeros_like(tide_time) elif (model.format == 'netcdf'): amp, ph, D, c = extract_netcdf_constants(lon, lat, model.grid_file, model.model_file, TYPE=model.type, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) deltat = np.zeros_like(tide_time) elif (model.format == 'GOT'): amp, ph, c = extract_GOT_constants(lon, lat, model.model_file, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, tide_time) elif (model.format == 'FES'): amp, ph = extract_FES_constants(lon, lat, model.model_file, TYPE=model.type, VERSION=model.version, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) #-- available model constituents c = model.constituents #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, tide_time) #-- calculate complex phase in radians for Euler's cph = -1j * ph * np.pi / 180.0 #-- calculate constituent oscillation hc = amp * np.exp(cph) #-- predict tidal elevations at time and infer minor corrections tide = np.ma.empty((n_seg), fill_value=fv) tide.mask = np.any(hc.mask, axis=1) tide.data[:] = predict_tide_drift(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model.format) minor = infer_minor_corrections(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model.format) tide.data[:] += minor.data[:] #-- replace masked and nan values with fill value invalid, = np.nonzero(np.isnan(tide.data) | tide.mask) tide.data[invalid] = tide.fill_value tide.mask[invalid] = True #-- group attributes for beam IS2_atl03_tide_attrs[gtx]['Description'] = attrs['Description'] IS2_atl03_tide_attrs[gtx]['atlas_pce'] = attrs['atlas_pce'] IS2_atl03_tide_attrs[gtx]['atlas_beam_type'] = attrs['atlas_beam_type'] IS2_atl03_tide_attrs[gtx]['groundtrack_id'] = attrs['groundtrack_id'] IS2_atl03_tide_attrs[gtx]['atmosphere_profile'] = attrs[ 'atmosphere_profile'] IS2_atl03_tide_attrs[gtx]['atlas_spot_number'] = attrs[ 'atlas_spot_number'] IS2_atl03_tide_attrs[gtx]['sc_orientation'] = attrs['sc_orientation'] #-- group attributes for geolocation IS2_atl03_tide_attrs[gtx]['geolocation']['Description'] = ( "Contains parameters related to " "geolocation. The rate of all of these parameters is at the rate corresponding to the " "ICESat-2 Geolocation Along Track Segment interval (nominally 20 m along-track)." ) IS2_atl03_tide_attrs[gtx]['geolocation']['data_rate'] = ( "Data within this group are " "stored at the ICESat-2 20m segment rate.") #-- group attributes for geophys_corr IS2_atl03_tide_attrs[gtx]['geophys_corr']['Description'] = ( "Contains parameters used to " "correct photon heights for geophysical effects, such as tides. These parameters are " "posted at the same interval as the ICESat-2 Geolocation Along-Track Segment interval " "(nominally 20m along-track).") IS2_atl03_tide_attrs[gtx]['geophys_corr']['data_rate'] = ( "These parameters are stored at " "the ICESat-2 Geolocation Along Track Segment rate (nominally every 20 m along-track)." ) #-- geolocation, time and segment ID #-- delta time in geolocation group IS2_atl03_tide[gtx]['geolocation']['delta_time'] = delta_time IS2_atl03_fill[gtx]['geolocation']['delta_time'] = None IS2_atl03_dims[gtx]['geolocation']['delta_time'] = None IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time'] = {} IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time'][ 'units'] = "seconds since 2018-01-01" IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time'][ 'long_name'] = "Elapsed GPS seconds" IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time'][ 'standard_name'] = "time" IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time'][ 'calendar'] = "standard" IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time']['description'] = ( "Elapsed seconds " "from the ATLAS SDP GPS Epoch, corresponding to the transmit time of the reference " "photon. The ATLAS Standard Data Products (SDP) epoch offset is defined within " "/ancillary_data/atlas_sdp_gps_epoch as the number of GPS seconds between the GPS epoch " "(1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP epoch. By adding the offset " "contained within atlas_sdp_gps_epoch to delta time parameters, the time in gps_seconds " "relative to the GPS epoch can be computed.") IS2_atl03_tide_attrs[gtx]['geolocation']['delta_time']['coordinates'] = \ "segment_id reference_photon_lat reference_photon_lon" #-- delta time in geophys_corr group IS2_atl03_tide[gtx]['geophys_corr']['delta_time'] = delta_time IS2_atl03_fill[gtx]['geophys_corr']['delta_time'] = None IS2_atl03_dims[gtx]['geophys_corr']['delta_time'] = None IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time'] = {} IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time'][ 'units'] = "seconds since 2018-01-01" IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time'][ 'long_name'] = "Elapsed GPS seconds" IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time'][ 'standard_name'] = "time" IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time'][ 'calendar'] = "standard" IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time']['description'] = ( "Elapsed seconds " "from the ATLAS SDP GPS Epoch, corresponding to the transmit time of the reference " "photon. The ATLAS Standard Data Products (SDP) epoch offset is defined within " "/ancillary_data/atlas_sdp_gps_epoch as the number of GPS seconds between the GPS epoch " "(1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP epoch. By adding the offset " "contained within atlas_sdp_gps_epoch to delta time parameters, the time in gps_seconds " "relative to the GPS epoch can be computed.") IS2_atl03_tide_attrs[gtx]['geophys_corr']['delta_time']['coordinates'] = ( "../geolocation/segment_id " "../geolocation/reference_photon_lat ../geolocation/reference_photon_lon" ) #-- latitude IS2_atl03_tide[gtx]['geolocation']['reference_photon_lat'] = lat IS2_atl03_fill[gtx]['geolocation']['reference_photon_lat'] = None IS2_atl03_dims[gtx]['geolocation']['reference_photon_lat'] = [ 'delta_time' ] IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'] = {} IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'units'] = "degrees_north" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'contentType'] = "physicalMeasurement" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'long_name'] = "Latitude" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'standard_name'] = "latitude" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'description'] = ( "Latitude of each " "reference photon. Computed from the ECF Cartesian coordinates of the bounce point." ) IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'valid_min'] = -90.0 IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat'][ 'valid_max'] = 90.0 IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lat']['coordinates'] = \ "segment_id delta_time reference_photon_lon" #-- longitude IS2_atl03_tide[gtx]['geolocation']['reference_photon_lon'] = lon IS2_atl03_fill[gtx]['geolocation']['reference_photon_lon'] = None IS2_atl03_dims[gtx]['geolocation']['reference_photon_lon'] = [ 'delta_time' ] IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'] = {} IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'units'] = "degrees_east" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'contentType'] = "physicalMeasurement" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'long_name'] = "Longitude" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'standard_name'] = "longitude" IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'description'] = ( "Longitude of each " "reference photon. Computed from the ECF Cartesian coordinates of the bounce point." ) IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'valid_min'] = -180.0 IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon'][ 'valid_max'] = 180.0 IS2_atl03_tide_attrs[gtx]['geolocation']['reference_photon_lon']['coordinates'] = \ "segment_id delta_time reference_photon_lat" #-- segment ID IS2_atl03_tide[gtx]['geolocation']['segment_id'] = segment_id IS2_atl03_fill[gtx]['geolocation']['segment_id'] = None IS2_atl03_dims[gtx]['geolocation']['segment_id'] = ['delta_time'] IS2_atl03_tide_attrs[gtx]['geolocation']['segment_id'] = {} IS2_atl03_tide_attrs[gtx]['geolocation']['segment_id']['units'] = "1" IS2_atl03_tide_attrs[gtx]['geolocation']['segment_id'][ 'contentType'] = "referenceInformation" IS2_atl03_tide_attrs[gtx]['geolocation']['segment_id'][ 'long_name'] = "Along-track segment ID number" IS2_atl03_tide_attrs[gtx]['geolocation']['segment_id']['description'] = ( "A 7 digit number " "identifying the along-track geolocation segment number. These are sequential, starting with " "1 for the first segment after an ascending equatorial crossing node. Equal to the segment_id for " "the second of the two 20m ATL03 segments included in the 40m ATL03 segment" ) IS2_atl03_tide_attrs[gtx]['geolocation']['segment_id']['coordinates'] = \ "delta_time reference_photon_lat reference_photon_lon" #-- computed tide IS2_atl03_tide[gtx]['geophys_corr'][model.atl03] = tide IS2_atl03_fill[gtx]['geophys_corr'][model.atl03] = tide.fill_value IS2_atl03_dims[gtx]['geophys_corr'][model.atl03] = ['delta_time'] IS2_atl03_tide_attrs[gtx]['geophys_corr'][model.atl03] = {} IS2_atl03_tide_attrs[gtx]['geophys_corr'][ model.atl03]['units'] = "meters" IS2_atl03_tide_attrs[gtx]['geophys_corr'][ model.atl03]['contentType'] = "referenceInformation" IS2_atl03_tide_attrs[gtx]['geophys_corr'][ model.atl03]['long_name'] = model.long_name IS2_atl03_tide_attrs[gtx]['geophys_corr'][ model.atl03]['description'] = model.description IS2_atl03_tide_attrs[gtx]['geophys_corr'][ model.atl03]['source'] = model.name IS2_atl03_tide_attrs[gtx]['geophys_corr'][ model.atl03]['reference'] = model.reference IS2_atl03_tide_attrs[gtx]['geophys_corr'][model.atl03]['coordinates'] = \ ("../geolocation/segment_id ../geolocation/delta_time " "../geolocation/reference_photon_lat ../geolocation/reference_photon_lon") #-- print file information logger.info('\t{0}'.format(OUTPUT_FILE)) HDF5_ATL03_tide_write(IS2_atl03_tide, IS2_atl03_tide_attrs, CLOBBER=True, INPUT=os.path.basename(INPUT_FILE), FILL_VALUE=IS2_atl03_fill, DIMENSIONS=IS2_atl03_dims, FILENAME=os.path.join(DIRECTORY, OUTPUT_FILE)) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY, OUTPUT_FILE), MODE)
def compute_tides_icebridge_data(tide_dir, arg, TIDE_MODEL, METHOD='spline', EXTRAPOLATE=False, VERBOSE=False, MODE=0o775): #-- extract file name and subsetter indices lists match_object = re.match(r'(.*?)(\[(.*?)\])?$',arg) input_file = os.path.expanduser(match_object.group(1)) #-- subset input file to indices if match_object.group(2): #-- decompress ranges and add to list input_subsetter = [] for i in re.findall(r'((\d+)-(\d+)|(\d+))',match_object.group(3)): input_subsetter.append(int(i[3])) if i[3] else \ input_subsetter.extend(range(int(i[1]),int(i[2])+1)) else: input_subsetter = None #-- output directory for input_file DIRECTORY = os.path.dirname(input_file) #-- calculate if input files are from ATM or LVIS (+GH) regex = {} regex['ATM'] = r'(BLATM2|ILATM2)_(\d+)_(\d+)_smooth_nadir(.*?)(csv|seg|pt)$' regex['ATM1b'] = r'(BLATM1b|ILATM1b)_(\d+)_(\d+)(.*?).(qi|TXT|h5)$' regex['LVIS'] = r'(BLVIS2|BVLIS2|ILVIS2)_(.*?)(\d+)_(\d+)_(R\d+)_(\d+).H5$' regex['LVGH'] = r'(ILVGH2)_(.*?)(\d+)_(\d+)_(R\d+)_(\d+).H5$' for key,val in regex.items(): if re.match(val, os.path.basename(input_file)): OIB = key #-- select between tide models if (TIDE_MODEL == 'CATS0201'): grid_file = os.path.join(tide_dir,'cats0201_tmd','grid_CATS') model_file = os.path.join(tide_dir,'cats0201_tmd','h0_CATS02_01') reference = 'https://mail.esr.org/polar_tide_models/Model_CATS0201.html' output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'CATS2008'): grid_file = os.path.join(tide_dir,'CATS2008','grid_CATS2008') model_file = os.path.join(tide_dir,'CATS2008','hf.CATS2008.out') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = 'CATS2008' TYPE = 'z' elif (TIDE_MODEL == 'CATS2008_load'): grid_file = os.path.join(tide_dir,'CATS2008a_SPOTL_Load','grid_CATS2008a_opt') model_file = os.path.join(tide_dir,'CATS2008a_SPOTL_Load','h_CATS2008a_SPOTL_load') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') output_variable = 'tide_load' variable_long_name = 'Load_Tide' model_format = 'OTIS' EPSG = 'CATS2008' TYPE = 'z' elif (TIDE_MODEL == 'TPXO9-atlas'): model_directory = os.path.join(tide_dir,'TPXO9_atlas') grid_file = os.path.join(model_directory,'grid_tpxo9_atlas.nc.gz') model_files = ['h_q1_tpxo9_atlas_30.nc.gz','h_o1_tpxo9_atlas_30.nc.gz', 'h_p1_tpxo9_atlas_30.nc.gz','h_k1_tpxo9_atlas_30.nc.gz', 'h_n2_tpxo9_atlas_30.nc.gz','h_m2_tpxo9_atlas_30.nc.gz', 'h_s2_tpxo9_atlas_30.nc.gz','h_k2_tpxo9_atlas_30.nc.gz', 'h_m4_tpxo9_atlas_30.nc.gz','h_ms4_tpxo9_atlas_30.nc.gz', 'h_mn4_tpxo9_atlas_30.nc.gz','h_2n2_tpxo9_atlas_30.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = 'http://volkov.oce.orst.edu/tides/tpxo9_atlas.html' output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'netcdf' TYPE = 'z' SCALE = 1.0/1000.0 GZIP = True elif (TIDE_MODEL == 'TPXO9-atlas-v2'): model_directory = os.path.join(tide_dir,'TPXO9_atlas_v2') grid_file = os.path.join(model_directory,'grid_tpxo9_atlas_30_v2.nc.gz') model_files = ['h_q1_tpxo9_atlas_30_v2.nc.gz','h_o1_tpxo9_atlas_30_v2.nc.gz', 'h_p1_tpxo9_atlas_30_v2.nc.gz','h_k1_tpxo9_atlas_30_v2.nc.gz', 'h_n2_tpxo9_atlas_30_v2.nc.gz','h_m2_tpxo9_atlas_30_v2.nc.gz', 'h_s2_tpxo9_atlas_30_v2.nc.gz','h_k2_tpxo9_atlas_30_v2.nc.gz', 'h_m4_tpxo9_atlas_30_v2.nc.gz','h_ms4_tpxo9_atlas_30_v2.nc.gz', 'h_mn4_tpxo9_atlas_30_v2.nc.gz','h_2n2_tpxo9_atlas_30_v2.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = 'https://www.tpxo.net/global/tpxo9-atlas' output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'netcdf' TYPE = 'z' SCALE = 1.0/1000.0 GZIP = True elif (TIDE_MODEL == 'TPXO9-atlas-v3'): model_directory = os.path.join(tide_dir,'TPXO9_atlas_v3') grid_file = os.path.join(model_directory,'grid_tpxo9_atlas_30_v3.nc.gz') model_files = ['h_q1_tpxo9_atlas_30_v3.nc.gz','h_o1_tpxo9_atlas_30_v3.nc.gz', 'h_p1_tpxo9_atlas_30_v3.nc.gz','h_k1_tpxo9_atlas_30_v3.nc.gz', 'h_n2_tpxo9_atlas_30_v3.nc.gz','h_m2_tpxo9_atlas_30_v3.nc.gz', 'h_s2_tpxo9_atlas_30_v3.nc.gz','h_k2_tpxo9_atlas_30_v3.nc.gz', 'h_m4_tpxo9_atlas_30_v3.nc.gz','h_ms4_tpxo9_atlas_30_v3.nc.gz', 'h_mn4_tpxo9_atlas_30_v3.nc.gz','h_2n2_tpxo9_atlas_30_v3.nc.gz', 'h_mf_tpxo9_atlas_30_v3.nc.gz','h_mm_tpxo9_atlas_30_v3.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = 'https://www.tpxo.net/global/tpxo9-atlas' output_variable = 'tide_ocean' variable_long_name = "Ocean Tide" model_format = 'netcdf' TYPE = 'z' SCALE = 1.0/1000.0 GZIP = True elif (TIDE_MODEL == 'TPXO9-atlas-v4'): model_directory = os.path.join(tide_dir,'TPXO9_atlas_v4') grid_file = os.path.join(model_directory,'grid_tpxo9_atlas_30_v4') model_files = ['h_q1_tpxo9_atlas_30_v4','h_o1_tpxo9_atlas_30_v4', 'h_p1_tpxo9_atlas_30_v4','h_k1_tpxo9_atlas_30_v4', 'h_n2_tpxo9_atlas_30_v4','h_m2_tpxo9_atlas_30_v4', 'h_s2_tpxo9_atlas_30_v4','h_k2_tpxo9_atlas_30_v4', 'h_m4_tpxo9_atlas_30_v4','h_ms4_tpxo9_atlas_30_v4', 'h_mn4_tpxo9_atlas_30_v4','h_2n2_tpxo9_atlas_30_v4', 'h_mf_tpxo9_atlas_30_v4','h_mm_tpxo9_atlas_30_v4'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = 'https://www.tpxo.net/global/tpxo9-atlas' output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO9.1'): grid_file = os.path.join(tide_dir,'TPXO9.1','DATA','grid_tpxo9') model_file = os.path.join(tide_dir,'TPXO9.1','DATA','h_tpxo9.v1') reference = 'http://volkov.oce.orst.edu/tides/global.html' output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO8-atlas'): grid_file = os.path.join(tide_dir,'tpxo8_atlas','grid_tpxo8atlas_30_v1') model_file = os.path.join(tide_dir,'tpxo8_atlas','hf.tpxo8_atlas_30_v1') reference = 'http://volkov.oce.orst.edu/tides/tpxo8_atlas.html' output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'ATLAS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO7.2'): grid_file = os.path.join(tide_dir,'TPXO7.2_tmd','grid_tpxo7.2') model_file = os.path.join(tide_dir,'TPXO7.2_tmd','h_tpxo7.2') reference = 'http://volkov.oce.orst.edu/tides/global.html' output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO7.2_load'): grid_file = os.path.join(tide_dir,'TPXO7.2_load','grid_tpxo6.2') model_file = os.path.join(tide_dir,'TPXO7.2_load','h_tpxo7.2_load') reference = 'http://volkov.oce.orst.edu/tides/global.html' output_variable = 'tide_load' variable_long_name = 'Load_Tide' model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'AODTM-5'): grid_file = os.path.join(tide_dir,'aodtm5_tmd','grid_Arc5km') model_file = os.path.join(tide_dir,'aodtm5_tmd','h0_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aodtm-5/') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'AOTIM-5'): grid_file = os.path.join(tide_dir,'aotim5_tmd','grid_Arc5km') model_file = os.path.join(tide_dir,'aotim5_tmd','h_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'AOTIM-5-2018'): grid_file = os.path.join(tide_dir,'Arc5km2018','grid_Arc5km2018') model_file = os.path.join(tide_dir,'Arc5km2018','h_Arc5km2018') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'GOT4.7'): model_directory = os.path.join(tide_dir,'GOT4.7','grids_oceantide') model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz', 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'GOT' SCALE = 1.0/100.0 GZIP = True elif (TIDE_MODEL == 'GOT4.7_load'): model_directory = os.path.join(tide_dir,'GOT4.7','grids_loadtide') model_files = ['q1load.d.gz','o1load.d.gz','p1load.d.gz','k1load.d.gz', 'n2load.d.gz','m2load.d.gz','s2load.d.gz','k2load.d.gz', 's1load.d.gz','m4load.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') output_variable = 'tide_load' variable_long_name = 'Load_Tide' model_format = 'GOT' SCALE = 1.0/1000.0 GZIP = True elif (TIDE_MODEL == 'GOT4.8'): model_directory = os.path.join(tide_dir,'got4.8','grids_oceantide') model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz', 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'GOT' SCALE = 1.0/100.0 GZIP = True elif (TIDE_MODEL == 'GOT4.8_load'): model_directory = os.path.join(tide_dir,'got4.8','grids_loadtide') model_files = ['q1load.d.gz','o1load.d.gz','p1load.d.gz','k1load.d.gz', 'n2load.d.gz','m2load.d.gz','s2load.d.gz','k2load.d.gz', 's1load.d.gz','m4load.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') output_variable = 'tide_load' variable_long_name = 'Load_Tide' model_format = 'GOT' SCALE = 1.0/1000.0 GZIP = True elif (TIDE_MODEL == 'GOT4.10'): model_directory = os.path.join(tide_dir,'GOT4.10c','grids_oceantide') model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz', 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'GOT' SCALE = 1.0/100.0 GZIP = True elif (TIDE_MODEL == 'GOT4.10_load'): model_directory = os.path.join(tide_dir,'GOT4.10c','grids_loadtide') model_files = ['q1load.d.gz','o1load.d.gz','p1load.d.gz','k1load.d.gz', 'n2load.d.gz','m2load.d.gz','s2load.d.gz','k2load.d.gz', 's1load.d.gz','m4load.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') output_variable = 'tide_load' variable_long_name = 'Load_Tide' model_format = 'GOT' SCALE = 1.0/1000.0 GZIP = True elif (TIDE_MODEL == 'FES2014'): model_directory = os.path.join(tide_dir,'fes2014','ocean_tide') model_files = ['2n2.nc.gz','eps2.nc.gz','j1.nc.gz','k1.nc.gz', 'k2.nc.gz','l2.nc.gz','la2.nc.gz','m2.nc.gz','m3.nc.gz','m4.nc.gz', 'm6.nc.gz','m8.nc.gz','mf.nc.gz','mks2.nc.gz','mm.nc.gz', 'mn4.nc.gz','ms4.nc.gz','msf.nc.gz','msqm.nc.gz','mtm.nc.gz', 'mu2.nc.gz','n2.nc.gz','n4.nc.gz','nu2.nc.gz','o1.nc.gz','p1.nc.gz', 'q1.nc.gz','r2.nc.gz','s1.nc.gz','s2.nc.gz','s4.nc.gz','sa.nc.gz', 'ssa.nc.gz','t2.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] c = ['2n2','eps2','j1','k1','k2','l2','lambda2','m2','m3','m4','m6', 'm8','mf','mks2','mm','mn4','ms4','msf','msqm','mtm','mu2','n2', 'n4','nu2','o1','p1','q1','r2','s1','s2','s4','sa','ssa','t2'] reference = ('https://www.aviso.altimetry.fr/en/data/products' 'auxiliary-products/global-tide-fes.html') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'FES' TYPE = 'z' SCALE = 1.0/100.0 GZIP = True elif (TIDE_MODEL == 'FES2014_load'): model_directory = os.path.join(tide_dir,'fes2014','load_tide') model_files = ['2n2.nc.gz','eps2.nc.gz','j1.nc.gz','k1.nc.gz', 'k2.nc.gz','l2.nc.gz','la2.nc.gz','m2.nc.gz','m3.nc.gz','m4.nc.gz', 'm6.nc.gz','m8.nc.gz','mf.nc.gz','mks2.nc.gz','mm.nc.gz', 'mn4.nc.gz','ms4.nc.gz','msf.nc.gz','msqm.nc.gz','mtm.nc.gz', 'mu2.nc.gz','n2.nc.gz','n4.nc.gz','nu2.nc.gz','o1.nc.gz','p1.nc.gz', 'q1.nc.gz','r2.nc.gz','s1.nc.gz','s2.nc.gz','s4.nc.gz','sa.nc.gz', 'ssa.nc.gz','t2.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] c = ['2n2','eps2','j1','k1','k2','l2','lambda2','m2','m3','m4','m6', 'm8','mf','mks2','mm','mn4','ms4','msf','msqm','mtm','mu2','n2', 'n4','nu2','o1','p1','q1','r2','s1','s2','s4','sa','ssa','t2'] reference = ('https://www.aviso.altimetry.fr/en/data/products' 'auxiliary-products/global-tide-fes.html') output_variable = 'tide_load' variable_long_name = 'Load_Tide' model_format = 'FES' TYPE = 'z' SCALE = 1.0/100.0 GZIP = True #-- HDF5 file attributes attrib = {} #-- latitude attrib['lat'] = {} attrib['lat']['long_name'] = 'Latitude_of_measurement' attrib['lat']['description'] = ('Corresponding_to_the_measurement_' 'position_at_the_acquisition_time') attrib['lat']['units'] = 'Degrees_North' #-- longitude attrib['lon'] = {} attrib['lon']['long_name'] = 'Longitude_of_measurement' attrib['lon']['description'] = ('Corresponding_to_the_measurement_' 'position_at_the_acquisition_time') attrib['lon']['units'] = 'Degrees_East' #-- tides attrib[output_variable] = {} attrib[output_variable]['description'] = ('Tidal_elevation_from_harmonic_' 'constants_at_the_measurement_position_at_the_acquisition_time') attrib[output_variable]['reference'] = reference attrib[output_variable]['model'] = TIDE_MODEL attrib[output_variable]['units'] = 'meters' attrib[output_variable]['long_name'] = variable_long_name #-- time attrib['time'] = {} attrib['time']['long_name'] = 'Time' attrib['time']['description'] = ('Time_corresponding_to_the_measurement_' 'position') attrib['time']['units'] = 'Days since 1992-01-01T00:00:00' attrib['time']['calendar'] = 'standard' #-- extract information from first input file #-- acquisition year, month and day #-- number of points #-- instrument (PRE-OIB ATM or LVIS, OIB ATM or LVIS) if OIB in ('ATM','ATM1b'): M1,YYMMDD1,HHMMSS1,AX1,SF1 = re.findall(regex[OIB], input_file).pop() #-- early date strings omitted century and millenia (e.g. 93 for 1993) if (len(YYMMDD1) == 6): ypre,MM1,DD1 = YYMMDD1[:2],YYMMDD1[2:4],YYMMDD1[4:] if (np.float64(ypre) >= 90): YY1 = '{0:4.0f}'.format(np.float64(ypre) + 1900.0) else: YY1 = '{0:4.0f}'.format(np.float64(ypre) + 2000.0) elif (len(YYMMDD1) == 8): YY1,MM1,DD1 = YYMMDD1[:4],YYMMDD1[4:6],YYMMDD1[6:] elif OIB in ('LVIS','LVGH'): M1,RG1,YY1,MMDD1,RLD1,SS1 = re.findall(regex[OIB], input_file).pop() MM1,DD1 = MMDD1[:2],MMDD1[2:] #-- read data from input_file print('{0} -->'.format(input_file)) if VERBOSE else None if (OIB == 'ATM'): #-- load IceBridge ATM data from input_file dinput,file_lines,HEM = read_ATM_icessn_file(input_file,input_subsetter) elif (OIB == 'ATM1b'): #-- load IceBridge Level-1b ATM data from input_file dinput,file_lines,HEM = read_ATM_qfit_file(input_file,input_subsetter) elif OIB in ('LVIS','LVGH'): #-- load IceBridge LVIS data from input_file dinput,file_lines,HEM = read_LVIS_HDF5_file(input_file,input_subsetter) #-- convert time from J2000 to days relative to Jan 1, 1992 (48622mjd) #-- J2000: seconds since 2000-01-01 12:00:00 UTC t = pyTMD.time.convert_delta_time(dinput['time'], epoch1=(2000,1,1,12,0,0), epoch2=(1992,1,1,0,0,0), scale=1.0/86400.0) #-- delta time (TT - UT1) file delta_file = get_data_path(['data','merged_deltat.data']) #-- read tidal constants and interpolate to grid points if model_format in ('OTIS','ATLAS'): amp,ph,D,c = extract_tidal_constants(dinput['lon'], dinput['lat'], grid_file, model_file, EPSG, TYPE=TYPE, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, GRID=model_format) deltat = np.zeros_like(t) elif model_format in ('netcdf'): amp,ph,D,c = extract_netcdf_constants(dinput['lon'], dinput['lat'], grid_file, model_file, TYPE=TYPE, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=SCALE, GZIP=GZIP) deltat = np.zeros_like(t) elif (model_format == 'GOT'): amp,ph,c = extract_GOT_constants(dinput['lon'], dinput['lat'], model_file, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=SCALE, GZIP=GZIP) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, t) elif (model_format == 'FES'): amp,ph = extract_FES_constants(dinput['lon'], dinput['lat'], model_file, TYPE=TYPE, VERSION=TIDE_MODEL, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=SCALE, GZIP=GZIP) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, t) #-- calculate complex phase in radians for Euler's cph = -1j*ph*np.pi/180.0 #-- calculate constituent oscillation hc = amp*np.exp(cph) #-- output tidal HDF5 file #-- form: rg_NASA_model_TIDES_WGS84_fl1yyyymmddjjjjj.H5 #-- where rg is the hemisphere flag (GR or AN) for the region #-- model is the tidal TIDE_MODEL flag (e.g. CATS0201) #-- fl1 and fl2 are the data flags (ATM, LVIS, GLAS) #-- yymmddjjjjj is the year, month, day and second of the input file #-- output region flags: GR for Greenland and AN for Antarctica hem_flag = {'N':'GR','S':'AN'} #-- use starting second to distinguish between files for the day JJ1 = np.min(dinput['time']) % 86400 #-- output file format args = (hem_flag[HEM],TIDE_MODEL,OIB,YY1,MM1,DD1,JJ1) FILENAME = '{0}_NASA_{1}_TIDES_WGS84_{2}{3}{4}{5}{6:05.0f}.H5'.format(*args) #-- print file information print('\t{0}'.format(FILENAME)) if VERBOSE else None #-- open output HDF5 file fid = h5py.File(os.path.join(DIRECTORY,FILENAME), 'w') #-- predict tidal elevations at time and infer minor corrections fill_value = -9999.0 tide = np.ma.empty((file_lines),fill_value=fill_value) tide.mask = np.any(hc.mask,axis=1) tide.data[:] = predict_tide_drift(t, hc, c, DELTAT=deltat, CORRECTIONS=model_format) minor = infer_minor_corrections(t, hc, c, DELTAT=deltat, CORRECTIONS=model_format) tide.data[:] += minor.data[:] #-- replace invalid values with fill value tide.data[tide.mask] = tide.fill_value #-- add latitude and longitude to output file for key in ['lat','lon']: #-- Defining the HDF5 dataset variables for lat/lon h5 = fid.create_dataset(key, (file_lines,), data=dinput[key][:], dtype=dinput[key].dtype, compression='gzip') #-- add HDF5 variable attributes for att_name,att_val in attrib[key].items(): h5.attrs[att_name] = att_val #-- attach dimensions h5.dims[0].label = 'RECORD_SIZE' #-- output tides to HDF5 dataset h5 = fid.create_dataset(output_variable, (file_lines,), data=tide, dtype=tide.dtype, fillvalue=fill_value, compression='gzip') #-- add HDF5 variable attributes tide_count = np.count_nonzero(tide != fill_value) h5.attrs['tide_count'] = tide_count h5.attrs['_FillValue'] = fill_value for att_name,att_val in attrib[output_variable].items(): h5.attrs[att_name] = att_val #-- attach dimensions h5.dims[0].label = 'RECORD_SIZE' #-- output days to HDF5 dataset h5 = fid.create_dataset('time', (file_lines,), data=t, dtype=t.dtype, compression='gzip') #-- add HDF5 variable attributes for att_name,att_val in attrib['time'].items(): h5.attrs[att_name] = att_val #-- attach dimensions h5.dims[0].label = 'RECORD_SIZE' #-- HDF5 file attributes fid.attrs['featureType'] = 'trajectory' fid.attrs['title'] = 'Tidal_correction_for_elevation_measurements' fid.attrs['summary'] = ('Tidal_correction_computed_at_elevation_' 'measurements_using_a_tidal_model_driver.') fid.attrs['project'] = 'NASA_Operation_IceBridge' fid.attrs['processing_level'] = '4' fid.attrs['date_created'] = time.strftime('%Y-%m-%d',time.localtime()) #-- add attributes for input file fid.attrs['elevation_file'] = os.path.basename(input_file) fid.attrs['tide_model'] = TIDE_MODEL #-- add geospatial and temporal attributes fid.attrs['geospatial_lat_min'] = dinput['lat'].min() fid.attrs['geospatial_lat_max'] = dinput['lat'].max() fid.attrs['geospatial_lon_min'] = dinput['lon'].min() fid.attrs['geospatial_lon_max'] = dinput['lon'].max() fid.attrs['geospatial_lat_units'] = "degrees_north" fid.attrs['geospatial_lon_units'] = "degrees_east" fid.attrs['geospatial_ellipsoid'] = "WGS84" fid.attrs['time_type'] = 'UTC' #-- convert start/end time from days since 1992-01-01 into Julian days time_range = np.array([np.min(t),np.max(t)]) time_julian = 2400000.5 + pyTMD.time.convert_delta_time(time_range, epoch1=(1992,1,1,0,0,0), epoch2=(1858,11,17,0,0,0), scale=1.0) #-- convert to calendar date cal = pyTMD.time.convert_julian(time_julian,ASTYPE=int) #-- add attributes with measurement date start, end and duration args = (cal['hour'][0],cal['minute'][0],cal['second'][0]) fid.attrs['RangeBeginningTime'] = '{0:02d}:{1:02d}:{2:02d}'.format(*args) args = (cal['hour'][-1],cal['minute'][-1],cal['second'][-1]) fid.attrs['RangeEndingTime'] = '{0:02d}:{1:02d}:{2:02d}'.format(*args) args = (cal['year'][0],cal['month'][0],cal['day'][0]) fid.attrs['RangeBeginningDate'] = '{0:4d}-{1:02d}-{2:02d}'.format(*args) args = (cal['year'][-1],cal['month'][-1],cal['day'][-1]) fid.attrs['RangeEndingDate'] = '{0:4d}-{1:02d}-{2:02d}'.format(*args) duration = np.round(time_julian[-1]*86400.0 - time_julian[0]*86400.0) fid.attrs['DurationTimeSeconds'] = '{0:0.0f}'.format(duration) #-- close the output HDF5 dataset fid.close() #-- change the permissions level to MODE os.chmod(os.path.join(DIRECTORY,FILENAME), MODE)
def compute_LPET_ICESat(INPUT_FILE, VERBOSE=False, MODE=0o775): #-- create logger for verbosity level loglevel = logging.INFO if VERBOSE else logging.CRITICAL logger = pyTMD.utilities.build_logger('pytmd', level=loglevel) #-- get directory from INPUT_FILE logger.info('{0} -->'.format(INPUT_FILE)) DIRECTORY = os.path.dirname(INPUT_FILE) #-- compile regular expression operator for extracting information from file rx = re.compile((r'GLAH(\d{2})_(\d{3})_(\d{1})(\d{1})(\d{2})_(\d{3})_' r'(\d{4})_(\d{1})_(\d{2})_(\d{4})\.H5'), re.VERBOSE) #-- extract parameters from ICESat/GLAS HDF5 file name #-- PRD: Product number (01, 05, 06, 12, 13, 14, or 15) #-- RL: Release number for process that created the product = 634 #-- RGTP: Repeat ground-track phase (1=8-day, 2=91-day, 3=transfer orbit) #-- ORB: Reference orbit number (starts at 1 and increments each time a #-- new reference orbit ground track file is obtained.) #-- INST: Instance number (increments every time the satellite enters a #-- different reference orbit) #-- CYCL: Cycle of reference orbit for this phase #-- TRK: Track within reference orbit #-- SEG: Segment of orbit #-- GRAN: Granule version number #-- TYPE: File type try: PRD, RL, RGTP, ORB, INST, CYCL, TRK, SEG, GRAN, TYPE = rx.findall( INPUT_FILE).pop() except: #-- output long-period equilibrium tide HDF5 file (generic) fileBasename, fileExtension = os.path.splitext(INPUT_FILE) OUTPUT_FILE = '{0}_{1}{2}'.format(fileBasename, 'LPET', fileExtension) else: #-- output long-period equilibrium tide HDF5 file for NSIDC granules args = (PRD, RL, RGTP, ORB, INST, CYCL, TRK, SEG, GRAN, TYPE) file_format = 'GLAH{0}_{1}_LPET_{2}{3}{4}_{5}_{6}_{7}_{8}_{9}.h5' OUTPUT_FILE = file_format.format(*args) #-- read GLAH12 HDF5 file fileID = h5py.File(INPUT_FILE, 'r') n_40HZ, = fileID['Data_40HZ']['Time']['i_rec_ndx'].shape #-- get variables and attributes rec_ndx_40HZ = fileID['Data_40HZ']['Time']['i_rec_ndx'][:].copy() #-- seconds since 2000-01-01 12:00:00 UTC (J2000) DS_UTCTime_40HZ = fileID['Data_40HZ']['DS_UTCTime_40'][:].copy() #-- Latitude (degrees North) lat_TPX = fileID['Data_40HZ']['Geolocation']['d_lat'][:].copy() #-- Longitude (degrees East) lon_40HZ = fileID['Data_40HZ']['Geolocation']['d_lon'][:].copy() #-- Elevation (height above TOPEX/Poseidon ellipsoid in meters) elev_TPX = fileID['Data_40HZ']['Elevation_Surfaces']['d_elev'][:].copy() fv = fileID['Data_40HZ']['Elevation_Surfaces']['d_elev'].attrs[ '_FillValue'] #-- semimajor axis (a) and flattening (f) for TP and WGS84 ellipsoids atop, ftop = (6378136.3, 1.0 / 298.257) awgs, fwgs = (6378137.0, 1.0 / 298.257223563) #-- convert from Topex/Poseidon to WGS84 Ellipsoids lat_40HZ, elev_40HZ = pyTMD.spatial.convert_ellipsoid(lat_TPX, elev_TPX, atop, ftop, awgs, fwgs, eps=1e-12, itmax=10) #-- convert time from J2000 to days relative to Jan 1, 1992 (48622mjd) #-- J2000: seconds since 2000-01-01 12:00:00 UTC tide_time = pyTMD.time.convert_delta_time(DS_UTCTime_40HZ, epoch1=(2000, 1, 1, 12, 0, 0), epoch2=(1992, 1, 1, 0, 0, 0), scale=1.0 / 86400.0) #-- interpolate delta times from calendar dates to tide time delta_file = pyTMD.utilities.get_data_path(['data', 'merged_deltat.data']) deltat = calc_delta_time(delta_file, tide_time) #-- predict long-period equilibrium tides at latitudes and time tide_lpe = compute_equilibrium_tide(tide_time + deltat, lat_40HZ) #-- copy variables for outputting to HDF5 file IS_gla12_tide = dict(Data_40HZ={}) IS_gla12_fill = dict(Data_40HZ={}) IS_gla12_tide_attrs = dict(Data_40HZ={}) #-- copy global file attributes global_attribute_list = [ 'featureType', 'title', 'comment', 'summary', 'license', 'references', 'AccessConstraints', 'CitationforExternalPublication', 'contributor_role', 'contributor_name', 'creator_name', 'creator_email', 'publisher_name', 'publisher_email', 'publisher_url', 'platform', 'instrument', 'processing_level', 'date_created', 'spatial_coverage_type', 'history', 'keywords', 'keywords_vocabulary', 'naming_authority', 'project', 'time_type', 'date_type', 'time_coverage_start', 'time_coverage_end', 'time_coverage_duration', 'source', 'HDFVersion', 'identifier_product_type', 'identifier_product_format_version', 'Conventions', 'institution', 'ReprocessingPlanned', 'ReprocessingActual', 'LocalGranuleID', 'ProductionDateTime', 'LocalVersionID', 'PGEVersion', 'OrbitNumber', 'StartOrbitNumber', 'StopOrbitNumber', 'EquatorCrossingLongitude', 'EquatorCrossingTime', 'EquatorCrossingDate', 'ShortName', 'VersionID', 'InputPointer', 'RangeBeginningTime', 'RangeEndingTime', 'RangeBeginningDate', 'RangeEndingDate', 'PercentGroundHit', 'OrbitQuality', 'Cycle', 'Track', 'Instrument_State', 'Timing_Bias', 'ReferenceOrbit', 'SP_ICE_PATH_NO', 'SP_ICE_GLAS_StartBlock', 'SP_ICE_GLAS_EndBlock', 'Instance', 'Range_Bias', 'Instrument_State_Date', 'Instrument_State_Time', 'Range_Bias_Date', 'Range_Bias_Time', 'Timing_Bias_Date', 'Timing_Bias_Time', 'identifier_product_doi', 'identifier_file_uuid', 'identifier_product_doi_authority' ] for att in global_attribute_list: IS_gla12_tide_attrs[att] = fileID.attrs[att] #-- copy ICESat campaign name from ancillary data IS_gla12_tide_attrs['Campaign'] = fileID['ANCILLARY_DATA'].attrs[ 'Campaign'] #-- add attributes for input GLA12 file IS_gla12_tide_attrs['input_files'] = os.path.basename(INPUT_FILE) #-- update geospatial ranges for ellipsoid IS_gla12_tide_attrs['geospatial_lat_min'] = np.min(lat_40HZ) IS_gla12_tide_attrs['geospatial_lat_max'] = np.max(lat_40HZ) IS_gla12_tide_attrs['geospatial_lon_min'] = np.min(lon_40HZ) IS_gla12_tide_attrs['geospatial_lon_max'] = np.max(lon_40HZ) IS_gla12_tide_attrs['geospatial_lat_units'] = "degrees_north" IS_gla12_tide_attrs['geospatial_lon_units'] = "degrees_east" IS_gla12_tide_attrs['geospatial_ellipsoid'] = "WGS84" #-- copy 40Hz group attributes for att_name, att_val in fileID['Data_40HZ'].attrs.items(): IS_gla12_tide_attrs['Data_40HZ'][att_name] = att_val #-- copy attributes for time, geolocation and geophysical groups for var in ['Time', 'Geolocation', 'Geophysical']: IS_gla12_tide['Data_40HZ'][var] = {} IS_gla12_fill['Data_40HZ'][var] = {} IS_gla12_tide_attrs['Data_40HZ'][var] = {} for att_name, att_val in fileID['Data_40HZ'][var].attrs.items(): IS_gla12_tide_attrs['Data_40HZ'][var][att_name] = att_val #-- J2000 time IS_gla12_tide['Data_40HZ']['DS_UTCTime_40'] = DS_UTCTime_40HZ IS_gla12_fill['Data_40HZ']['DS_UTCTime_40'] = None IS_gla12_tide_attrs['Data_40HZ']['DS_UTCTime_40'] = {} for att_name, att_val in fileID['Data_40HZ']['DS_UTCTime_40'].attrs.items( ): if att_name not in ('DIMENSION_LIST', 'CLASS', 'NAME'): IS_gla12_tide_attrs['Data_40HZ']['DS_UTCTime_40'][ att_name] = att_val #-- record IS_gla12_tide['Data_40HZ']['Time']['i_rec_ndx'] = rec_ndx_40HZ IS_gla12_fill['Data_40HZ']['Time']['i_rec_ndx'] = None IS_gla12_tide_attrs['Data_40HZ']['Time']['i_rec_ndx'] = {} for att_name, att_val in fileID['Data_40HZ']['Time'][ 'i_rec_ndx'].attrs.items(): if att_name not in ('DIMENSION_LIST', 'CLASS', 'NAME'): IS_gla12_tide_attrs['Data_40HZ']['Time']['i_rec_ndx'][ att_name] = att_val #-- latitude IS_gla12_tide['Data_40HZ']['Geolocation']['d_lat'] = lat_40HZ IS_gla12_fill['Data_40HZ']['Geolocation']['d_lat'] = None IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lat'] = {} for att_name, att_val in fileID['Data_40HZ']['Geolocation'][ 'd_lat'].attrs.items(): if att_name not in ('DIMENSION_LIST', 'CLASS', 'NAME'): IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lat'][ att_name] = att_val #-- longitude IS_gla12_tide['Data_40HZ']['Geolocation']['d_lon'] = lon_40HZ IS_gla12_fill['Data_40HZ']['Geolocation']['d_lon'] = None IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lon'] = {} for att_name, att_val in fileID['Data_40HZ']['Geolocation'][ 'd_lon'].attrs.items(): if att_name not in ('DIMENSION_LIST', 'CLASS', 'NAME'): IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lon'][ att_name] = att_val #-- geophysical variables #-- computed long-period equilibrium tide IS_gla12_tide['Data_40HZ']['Geophysical']['d_eqElv'] = tide_lpe IS_gla12_fill['Data_40HZ']['Geophysical']['d_eqElv'] = None IS_gla12_tide_attrs['Data_40HZ']['Geophysical']['d_eqElv'] = {} IS_gla12_tide_attrs['Data_40HZ']['Geophysical']['d_eqElv'][ 'units'] = "meters" IS_gla12_tide_attrs['Data_40HZ']['Geophysical']['d_eqElv']['long_name'] = \ "Long Period Equilibrium Tide" IS_gla12_tide_attrs['Data_40HZ']['Geophysical']['d_eqElv']['description'] = ( "Long-period " "equilibrium tidal elevation from the summation of fifteen tidal spectral lines" ) IS_gla12_tide_attrs['Data_40HZ']['Geophysical']['d_eqElv']['reference'] = \ "https://doi.org/10.1111/j.1365-246X.1973.tb03420.x" IS_gla12_tide_attrs['Data_40HZ']['Geophysical']['d_eqElv']['coordinates'] = \ "../DS_UTCTime_40" #-- close the input HDF5 file fileID.close() #-- print file information logger.info('\t{0}'.format(OUTPUT_FILE)) HDF5_GLA12_tide_write(IS_gla12_tide, IS_gla12_tide_attrs, FILENAME=os.path.join(DIRECTORY, OUTPUT_FILE), FILL_VALUE=IS_gla12_fill, CLOBBER=True) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY, OUTPUT_FILE), MODE)
def compute_tidal_elevations(tide_dir, input_file, output_file, TIDE_MODEL='', MODE=0775): #-- read input *.csv file to extract MJD, latitude, longitude and elevation dtype = dict(names=('MJD', 'lat', 'lon', 'h'), formats=('f8', 'f8', 'f8', 'f8')) dinput = np.loadtxt(input_file, delimiter=',', dtype=dtype) #-- select between tide models if (TIDE_MODEL == 'CATS0201'): grid_file = os.path.join(tide_dir, 'cats0201_tmd', 'grid_CATS') model_file = os.path.join(tide_dir, 'cats0201_tmd', 'h0_CATS02_01') reference = 'https://mail.esr.org/polar_tide_models/Model_CATS0201.html' model_format = 'OTIS' EPSG = '4326' type = 'z' elif (TIDE_MODEL == 'CATS2008'): grid_file = os.path.join(tide_dir, 'CATS2008', 'grid_CATS2008a_opt') model_file = os.path.join(tide_dir, 'CATS2008', 'hf.CATS2008.out') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') model_format = 'OTIS' EPSG = 'CATS2008' type = 'z' elif (TIDE_MODEL == 'CATS2008_load'): grid_file = os.path.join(tide_dir, 'CATS2008a_SPOTL_Load', 'grid_CATS2008a_opt') model_file = os.path.join(tide_dir, 'CATS2008a_SPOTL_Load', 'h_CATS2008a_SPOTL_load') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') model_format = 'OTIS' EPSG = 'CATS2008' type = 'z' elif (MODEL == 'TPXO9-atlas'): model_directory = os.path.join(tide_dir, 'TPXO9_atlas') grid_file = 'grid_tpxo9_atlas.nc.gz' model_files = [ 'h_q1_tpxo9_atlas_30.nc.gz', 'h_o1_tpxo9_atlas_30.nc.gz', 'h_p1_tpxo9_atlas_30.nc.gz', 'h_k1_tpxo9_atlas_30.nc.gz', 'h_n2_tpxo9_atlas_30.nc.gz', 'h_m2_tpxo9_atlas_30.nc.gz', 'h_s2_tpxo9_atlas_30.nc.gz', 'h_k2_tpxo9_atlas_30.nc.gz', 'h_m4_tpxo9_atlas_30.nc.gz', 'h_ms4_tpxo9_atlas_30.nc.gz', 'h_mn4_tpxo9_atlas_30.nc.gz', 'h_2n2_tpxo9_atlas_30.nc.gz' ] reference = 'http://volkov.oce.orst.edu/tides/tpxo9_atlas.html' model_format = 'netcdf' type = 'z' SCALE = 1.0 / 1000.0 elif (MODEL == 'TPXO9.1'): grid_file = os.path.join(tide_dir, 'TPXO9.1', 'DATA', 'grid_tpxo9') model_file = os.path.join(tide_dir, 'TPXO9.1', 'DATA', 'h_tpxo9.v1') reference = 'http://volkov.oce.orst.edu/tides/global.html' model_format = 'OTIS' EPSG = '4326' type = 'z' elif (MODEL == 'TPXO8-atlas'): grid_file = os.path.join(tide_dir, 'tpxo8_atlas', 'grid_tpxo8atlas_30_v1') model_file = os.path.join(tide_dir, 'tpxo8_atlas', 'hf.tpxo8_atlas_30_v1') reference = 'http://volkov.oce.orst.edu/tides/tpxo8_atlas.html' model_format = 'ATLAS' EPSG = '4326' type = 'z' elif (TIDE_MODEL == 'TPXO7.2'): grid_file = os.path.join(tide_dir, 'TPXO7.2_tmd', 'grid_tpxo7.2') model_file = os.path.join(tide_dir, 'TPXO7.2_tmd', 'h_tpxo7.2') reference = 'http://volkov.oce.orst.edu/tides/global.html' model_format = 'OTIS' EPSG = '4326' type = 'z' elif (TIDE_MODEL == 'TPXO7.2_load'): grid_file = os.path.join(tide_dir, 'TPXO7.2_load', 'grid_tpxo6.2') model_file = os.path.join(tide_dir, 'TPXO7.2_load', 'h_tpxo7.2_load') reference = 'http://volkov.oce.orst.edu/tides/global.html' model_format = 'OTIS' EPSG = '4326' type = 'z' elif (TIDE_MODEL == 'AODTM-5'): grid_file = os.path.join(tide_dir, 'aodtm5_tmd', 'grid_Arc5km') model_file = os.path.join(tide_dir, 'aodtm5_tmd', 'h0_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aodtm-5/') model_format = 'OTIS' EPSG = '3996' type = 'z' elif (TIDE_MODEL == 'AOTIM-5'): grid_file = os.path.join(tide_dir, 'aotim5_tmd', 'grid_Arc5km') model_file = os.path.join(tide_dir, 'aotim5_tmd', 'h_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') model_format = 'OTIS' EPSG = '3996' type = 'z' elif (TIDE_MODEL == 'GOT4.7'): model_directory = os.path.join(tide_dir, 'GOT4.7', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') model_format = 'GOT' SCALE = 1.0 / 100.0 elif (TIDE_MODEL == 'GOT4.7_load'): model_directory = os.path.join(tide_dir, 'GOT4.7', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') model_format = 'GOT' SCALE = 1.0 / 1000.0 elif (TIDE_MODEL == 'GOT4.8'): model_directory = os.path.join(tide_dir, 'got4.8', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') model_format = 'GOT' SCALE = 1.0 / 100.0 elif (TIDE_MODEL == 'GOT4.8_load'): model_directory = os.path.join(tide_dir, 'got4.8', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') model_format = 'GOT' SCALE = 1.0 / 1000.0 elif (TIDE_MODEL == 'GOT4.10'): model_directory = os.path.join(tide_dir, 'GOT4.10c', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') model_format = 'GOT' SCALE = 1.0 / 100.0 elif (TIDE_MODEL == 'GOT4.10_load'): model_directory = os.path.join(tide_dir, 'GOT4.10c', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') model_format = 'GOT' SCALE = 1.0 / 1000.0 #-- read tidal constants and interpolate to grid points if model_format in ('OTIS', 'ATLAS'): amp, ph, D, c = extract_tidal_constants(dinput['lon'], dinput['lat'], grid_file, model_file, EPSG, type, METHOD='spline') deltat = np.zeros_like(dinput['MJD']) elif (model_format == 'netcdf'): amp, ph, D, c = extract_netcdf_constants(dinput['lon'], dinput['lat'], model_directory, grid_file, model_files, type, METHOD='spline', SCALE=SCALE) deltat = np.zeros_like(dinput['MJD']) elif (model_format == 'GOT'): amp, ph = extract_GOT_constants(dinput['lon'], dinput['lat'], model_directory, model_files, METHOD='spline', SCALE=SCALE) delta_file = os.path.join(tide_dir, 'deltat.data') deltat = calc_delta_time(delta_file, dinput['MJD']) #-- convert phase to radians cph = -1j * ph * np.pi / 180.0 hc = amp * np.exp(cph) #-- convert time from MJD to days relative to Jan 1, 1992 (48622 MJD) #-- predict tidal elevations at time 1 and infer minor corrections tide = predict_tide_drift(dinput['MJD'] - 48622.0, hc, c, DELTAT=deltat, CORRECTIONS=model_format) tide += infer_minor_corrections(dinput['MJD'] - 48622.0, hc, c, DELTAT=deltat, CORRECTIONS=model_format) #-- replace invalid values with fill value fill_value = -9999.0 tide.data[tide.mask] = fill_value #-- output to file with open(output_file, 'w') as f: for d, lt, ln, td in zip(dinput['MJD'], dinput['lat'], dinput['lon'], tide): f.write('{0:0.6f},{1:0.2f},{2:0.2f},{3:0.2f}\n'.format( d, lt, ln, td)) #-- change the permissions level to MODE os.chmod(output_file, MODE)
def compute_LPET_icebridge_data(arg, VERBOSE=False, MODE=0o775): #-- extract file name and subsetter indices lists match_object = re.match(r'(.*?)(\[(.*?)\])?$', arg) input_file = os.path.expanduser(match_object.group(1)) #-- subset input file to indices if match_object.group(2): #-- decompress ranges and add to list input_subsetter = [] for i in re.findall(r'((\d+)-(\d+)|(\d+))', match_object.group(3)): input_subsetter.append(int(i[3])) if i[3] else \ input_subsetter.extend(range(int(i[1]),int(i[2])+1)) else: input_subsetter = None #-- output directory for input_file DIRECTORY = os.path.dirname(input_file) #-- calculate if input files are from ATM or LVIS (+GH) regex = {} regex[ 'ATM'] = r'(BLATM2|ILATM2)_(\d+)_(\d+)_smooth_nadir(.*?)(csv|seg|pt)$' regex['ATM1b'] = r'(BLATM1b|ILATM1b)_(\d+)_(\d+)(.*?).(qi|TXT|h5)$' regex['LVIS'] = r'(BLVIS2|BVLIS2|ILVIS2)_(.*?)(\d+)_(\d+)_(R\d+)_(\d+).H5$' regex['LVGH'] = r'(ILVGH2)_(.*?)(\d+)_(\d+)_(R\d+)_(\d+).H5$' for key, val in regex.items(): if re.match(val, os.path.basename(input_file)): OIB = key #-- HDF5 file attributes attrib = dict(lon={}, lat={}, tide_lpe={}, day={}) #-- latitude attrib['lat']['long_name'] = 'Latitude_of_measurement' attrib['lat']['description'] = ('Corresponding_to_the_measurement_' 'position_at_the_acquisition_time') attrib['lat']['units'] = 'Degrees_North' #-- longitude attrib['lon']['long_name'] = 'Longitude_of_measurement' attrib['lon']['description'] = ('Corresponding_to_the_measurement_' 'position_at_the_acquisition_time') attrib['lon']['units'] = 'Degrees_East' #-- long-period equilibrium tides attrib['tide_lpe']['long_name'] = 'Equilibrium_Tide' attrib['tide_lpe']['description'] = ( 'Long-period_equilibrium_tidal_elevation_' 'from_the_summation_of_fifteen_tidal_spectral_lines_at_the_measurement_' 'position_at_the_acquisition_time') attrib['tide_lpe']['reference'] = ('https://doi.org/10.1111/' 'j.1365-246X.1973.tb03420.x') attrib['tide_lpe']['units'] = 'meters' #-- time attrib['time'] = {} attrib['time']['long_name'] = 'Time' attrib['time']['units'] = 'days since 1992-01-01T00:00:00' attrib['time']['calendar'] = 'standard' #-- extract information from first input file #-- acquisition year, month and day #-- number of points #-- instrument (PRE-OIB ATM or LVIS, OIB ATM or LVIS) if OIB in ('ATM', 'ATM1b'): M1, YYMMDD1, HHMMSS1, AX1, SF1 = re.findall(regex[OIB], input_file).pop() #-- early date strings omitted century and millenia (e.g. 93 for 1993) if (len(YYMMDD1) == 6): ypre, MM1, DD1 = YYMMDD1[:2], YYMMDD1[2:4], YYMMDD1[4:] if (np.float(ypre) >= 90): YY1 = '{0:4.0f}'.format(np.float(ypre) + 1900.0) else: YY1 = '{0:4.0f}'.format(np.float(ypre) + 2000.0) elif (len(YYMMDD1) == 8): YY1, MM1, DD1 = YYMMDD1[:4], YYMMDD1[4:6], YYMMDD1[6:] elif OIB in ('LVIS', 'LVGH'): M1, RG1, YY1, MMDD1, RLD1, SS1 = re.findall(regex[OIB], input_file).pop() MM1, DD1 = MMDD1[:2], MMDD1[2:] #-- read data from input_file print('{0} -->'.format(input_file)) if VERBOSE else None if (OIB == 'ATM'): #-- load IceBridge ATM data from input_file dinput, file_lines, HEM = read_ATM_icessn_file(input_file, input_subsetter) elif (OIB == 'ATM1b'): #-- load IceBridge Level-1b ATM data from input_file dinput, file_lines, HEM = read_ATM_qfit_file(input_file, input_subsetter) elif OIB in ('LVIS', 'LVGH'): #-- load IceBridge LVIS data from input_file dinput, file_lines, HEM = read_LVIS_HDF5_file(input_file, input_subsetter) #-- convert time from J2000 to days relative to Jan 1, 1992 (48622mjd) #-- J2000: seconds since 2000-01-01 12:00:00 UTC tide_time = pyTMD.time.convert_delta_time(dinput['time'], epoch1=(2000, 1, 1, 12, 0, 0), epoch2=(1992, 1, 1, 0, 0, 0), scale=1.0 / 86400.0) #-- interpolate delta times from calendar dates to tide time delta_file = get_data_path(['data', 'merged_deltat.data']) deltat = calc_delta_time(delta_file, tide_time) #-- output tidal HDF5 file #-- form: rg_NASA_model_EQUILIBRIUM_TIDES_WGS84_fl1yyyymmddjjjjj.H5 #-- where rg is the hemisphere flag (GR or AN) for the region #-- fl1 and fl2 are the data flags (ATM, LVIS, GLAS) #-- yymmddjjjjj is the year, month, day and second of the input file #-- output region flags: GR for Greenland and AN for Antarctica hem_flag = {'N': 'GR', 'S': 'AN'} #-- use starting second to distinguish between files for the day JJ1 = np.min(dinput['time']) % 86400 #-- output file format file_format = '{0}_NASA_EQUILIBRIUM_TIDES_WGS84_{1}{2}{3}{4}{5:05.0f}.H5' FILENAME = file_format.format(hem_flag[HEM], OIB, YY1, MM1, DD1, JJ1) #-- print file information print('\t{0}'.format(FILENAME)) if VERBOSE else None #-- open output HDF5 file fid = h5py.File(os.path.join(DIRECTORY, FILENAME), 'w') #-- predict long-period equilibrium tides at time tide_lpe = compute_equilibrium_tide(tide_time + deltat, dinput['lat']) #-- add latitude and longitude to output file for key in ['lat', 'lon']: #-- Defining the HDF5 dataset variables for lat/lon h5 = fid.create_dataset(key, (file_lines, ), data=dinput[key][:], dtype=dinput[key].dtype, compression='gzip') #-- add HDF5 variable attributes for att_name, att_val in attrib[key].items(): h5.attrs[att_name] = att_val #-- attach dimensions h5.dims[0].label = 'RECORD_SIZE' #-- output tides to HDF5 dataset h5 = fid.create_dataset('tide_lpe', (file_lines, ), data=tide_lpe, dtype=tide_lpe.dtype, compression='gzip') #-- add HDF5 variable attributes for att_name, att_val in attrib['tide_lpe'].items(): h5.attrs[att_name] = att_val #-- attach dimensions h5.dims[0].label = 'RECORD_SIZE' #-- output days to HDF5 dataset h5 = fid.create_dataset('time', (file_lines, ), data=tide_time, dtype=tide_time.dtype, compression='gzip') #-- add HDF5 variable attributes for att_name, att_val in attrib['time'].items(): h5.attrs[att_name] = att_val #-- attach dimensions h5.dims[0].label = 'RECORD_SIZE' #-- HDF5 file attributes fid.attrs['featureType'] = 'trajectory' fid.attrs['title'] = ('Long-Period_Equilibrium_tidal_correction_for_' 'elevation_measurements') fid.attrs['summary'] = ('Tidal_correction_computed_at_elevation_' 'measurements_using_fifteen_spectral_lines.') fid.attrs['project'] = 'NASA_Operation_IceBridge' fid.attrs['processing_level'] = '4' fid.attrs['date_created'] = time.strftime('%Y-%m-%d', time.localtime()) #-- add attributes for input files fid.attrs['elevation_file'] = os.path.basename(input_file) #-- add geospatial and temporal attributes fid.attrs['geospatial_lat_min'] = dinput['lat'].min() fid.attrs['geospatial_lat_max'] = dinput['lat'].max() fid.attrs['geospatial_lon_min'] = dinput['lon'].min() fid.attrs['geospatial_lon_max'] = dinput['lon'].max() fid.attrs['geospatial_lat_units'] = "degrees_north" fid.attrs['geospatial_lon_units'] = "degrees_east" fid.attrs['geospatial_ellipsoid'] = "WGS84" fid.attrs['time_type'] = 'UTC' #-- convert start/end time from days since 1992-01-01 into Julian days time_range = np.array([np.min(tide_time), np.max(tide_time)]) time_julian = 2400000.5 + pyTMD.time.convert_delta_time( time_range, epoch1=(1992, 1, 1, 0, 0, 0), epoch2=(1858, 11, 17, 0, 0, 0), scale=1.0) #-- convert to calendar date cal = pyTMD.time.convert_julian(time_julian, ASTYPE=np.int) #-- add attributes with measurement date start, end and duration args = (cal['hour'][0], cal['minute'][0], cal['second'][0]) fid.attrs['RangeBeginningTime'] = '{0:02d}:{1:02d}:{2:02d}'.format(*args) args = (cal['hour'][-1], cal['minute'][-1], cal['second'][-1]) fid.attrs['RangeEndingTime'] = '{0:02d}:{1:02d}:{2:02d}'.format(*args) args = (cal['year'][0], cal['month'][0], cal['day'][0]) fid.attrs['RangeBeginningDate'] = '{0:4d}-{1:02d}-{2:02d}'.format(*args) args = (cal['year'][-1], cal['month'][-1], cal['day'][-1]) fid.attrs['RangeEndingDate'] = '{0:4d}-{1:02d}-{2:02d}'.format(*args) duration = np.round(time_julian[-1] * 86400.0 - time_julian[0] * 86400.0) fid.attrs['DurationTimeSeconds'] = '{0:0.0f}'.format(duration) #-- close the output HDF5 dataset fid.close() #-- change the permissions level to MODE os.chmod(os.path.join(DIRECTORY, FILENAME), MODE)
def compute_tides_icebridge_data(tide_dir, arg, TIDE_MODEL, ATLAS_FORMAT=None, GZIP=True, DEFINITION_FILE=None, METHOD='spline', EXTRAPOLATE=False, CUTOFF=None, VERBOSE=False, MODE=0o775): #-- create logger for verbosity level loglevel = logging.INFO if VERBOSE else logging.CRITICAL logger = pyTMD.utilities.build_logger('pytmd',level=loglevel) #-- get parameters for tide model if DEFINITION_FILE is not None: model = pyTMD.model(tide_dir).from_file(DEFINITION_FILE) else: model = pyTMD.model(tide_dir, format=ATLAS_FORMAT, compressed=GZIP).elevation(TIDE_MODEL) #-- extract file name and subsetter indices lists match_object = re.match(r'(.*?)(\[(.*?)\])?$',arg) input_file = os.path.expanduser(match_object.group(1)) #-- subset input file to indices if match_object.group(2): #-- decompress ranges and add to list input_subsetter = [] for i in re.findall(r'((\d+)-(\d+)|(\d+))',match_object.group(3)): input_subsetter.append(int(i[3])) if i[3] else \ input_subsetter.extend(range(int(i[1]),int(i[2])+1)) else: input_subsetter = None #-- output directory for input_file DIRECTORY = os.path.dirname(input_file) #-- calculate if input files are from ATM or LVIS (+GH) regex = {} regex['ATM'] = r'(BLATM2|ILATM2)_(\d+)_(\d+)_smooth_nadir(.*?)(csv|seg|pt)$' regex['ATM1b'] = r'(BLATM1b|ILATM1b)_(\d+)_(\d+)(.*?).(qi|TXT|h5)$' regex['LVIS'] = r'(BLVIS2|BVLIS2|ILVIS2)_(.*?)(\d+)_(\d+)_(R\d+)_(\d+).H5$' regex['LVGH'] = r'(ILVGH2)_(.*?)(\d+)_(\d+)_(R\d+)_(\d+).H5$' for key,val in regex.items(): if re.match(val, os.path.basename(input_file)): OIB = key #-- HDF5 file attributes attrib = collections.OrderedDict() #-- time attrib['time'] = {} attrib['time']['long_name'] = 'Time' attrib['time']['description'] = ('Time_corresponding_to_the_measurement_' 'position') attrib['time']['units'] = 'Days since 1992-01-01T00:00:00' attrib['time']['standard_name'] = 'time' attrib['time']['calendar'] = 'standard' #-- latitude attrib['lat'] = {} attrib['lat']['long_name'] = 'Latitude_of_measurement' attrib['lat']['description'] = ('Corresponding_to_the_measurement_' 'position_at_the_acquisition_time') attrib['lat']['units'] = 'Degrees_North' #-- longitude attrib['lon'] = {} attrib['lon']['long_name'] = 'Longitude_of_measurement' attrib['lon']['description'] = ('Corresponding_to_the_measurement_' 'position_at_the_acquisition_time') attrib['lon']['units'] = 'Degrees_East' #-- tides attrib[model.variable] = {} attrib[model.variable]['description'] = model.description attrib[model.variable]['reference'] = model.reference attrib[model.variable]['model'] = model.name attrib[model.variable]['units'] = 'meters' attrib[model.variable]['long_name'] = model.long_name #-- extract information from first input file #-- acquisition year, month and day #-- number of points #-- instrument (PRE-OIB ATM or LVIS, OIB ATM or LVIS) if OIB in ('ATM','ATM1b'): M1,YYMMDD1,HHMMSS1,AX1,SF1 = re.findall(regex[OIB], input_file).pop() #-- early date strings omitted century and millenia (e.g. 93 for 1993) if (len(YYMMDD1) == 6): ypre,MM1,DD1 = YYMMDD1[:2],YYMMDD1[2:4],YYMMDD1[4:] if (np.float64(ypre) >= 90): YY1 = '{0:4.0f}'.format(np.float64(ypre) + 1900.0) else: YY1 = '{0:4.0f}'.format(np.float64(ypre) + 2000.0) elif (len(YYMMDD1) == 8): YY1,MM1,DD1 = YYMMDD1[:4],YYMMDD1[4:6],YYMMDD1[6:] elif OIB in ('LVIS','LVGH'): M1,RG1,YY1,MMDD1,RLD1,SS1 = re.findall(regex[OIB], input_file).pop() MM1,DD1 = MMDD1[:2],MMDD1[2:] #-- read data from input_file logger.info('{0} -->'.format(input_file)) if (OIB == 'ATM'): #-- load IceBridge ATM data from input_file dinput,file_lines,HEM = read_ATM_icessn_file(input_file,input_subsetter) elif (OIB == 'ATM1b'): #-- load IceBridge Level-1b ATM data from input_file dinput,file_lines,HEM = read_ATM_qfit_file(input_file,input_subsetter) elif OIB in ('LVIS','LVGH'): #-- load IceBridge LVIS data from input_file dinput,file_lines,HEM = read_LVIS_HDF5_file(input_file,input_subsetter) #-- convert time from J2000 to days relative to Jan 1, 1992 (48622mjd) #-- J2000: seconds since 2000-01-01 12:00:00 UTC t = pyTMD.time.convert_delta_time(dinput['time'], epoch1=(2000,1,1,12,0,0), epoch2=(1992,1,1,0,0,0), scale=1.0/86400.0) #-- delta time (TT - UT1) file delta_file = pyTMD.utilities.get_data_path(['data','merged_deltat.data']) #-- read tidal constants and interpolate to grid points if model.format in ('OTIS','ATLAS'): amp,ph,D,c = extract_tidal_constants(dinput['lon'], dinput['lat'], model.grid_file, model.model_file, model.projection, TYPE=model.type, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, GRID=model.format) deltat = np.zeros_like(t) elif model.format in ('netcdf'): amp,ph,D,c = extract_netcdf_constants(dinput['lon'], dinput['lat'], model.grid_file, model.model_file, TYPE=model.type, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) deltat = np.zeros_like(t) elif (model.format == 'GOT'): amp,ph,c = extract_GOT_constants(dinput['lon'], dinput['lat'], model.model_file, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, t) elif (model.format == 'FES'): amp,ph = extract_FES_constants(dinput['lon'], dinput['lat'], model.model_file, TYPE=model.type, VERSION=model.version, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) #-- available model constituents c = model.constituents #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, t) #-- calculate complex phase in radians for Euler's cph = -1j*ph*np.pi/180.0 #-- calculate constituent oscillation hc = amp*np.exp(cph) #-- output tidal HDF5 file #-- form: rg_NASA_model_TIDES_WGS84_fl1yyyymmddjjjjj.H5 #-- where rg is the hemisphere flag (GR or AN) for the region #-- model is the tidal model name flag (e.g. CATS0201) #-- fl1 and fl2 are the data flags (ATM, LVIS, GLAS) #-- yymmddjjjjj is the year, month, day and second of the input file #-- output region flags: GR for Greenland and AN for Antarctica hem_flag = {'N':'GR','S':'AN'} #-- use starting second to distinguish between files for the day JJ1 = np.min(dinput['time']) % 86400 #-- output file format args = (hem_flag[HEM],model.name,OIB,YY1,MM1,DD1,JJ1) FILENAME = '{0}_NASA_{1}_TIDES_WGS84_{2}{3}{4}{5}{6:05.0f}.H5'.format(*args) #-- print file information logger.info('\t{0}'.format(FILENAME)) #-- open output HDF5 file fid = h5py.File(os.path.join(DIRECTORY,FILENAME), 'w') #-- predict tidal elevations at time and infer minor corrections fill_value = -9999.0 tide = np.ma.empty((file_lines),fill_value=fill_value) tide.mask = np.any(hc.mask,axis=1) tide.data[:] = predict_tide_drift(t, hc, c, DELTAT=deltat, CORRECTIONS=model.format) minor = infer_minor_corrections(t, hc, c, DELTAT=deltat, CORRECTIONS=model.format) tide.data[:] += minor.data[:] #-- replace invalid values with fill value tide.data[tide.mask] = tide.fill_value #-- copy tide to output variable dinput[model.variable] = tide.copy() #-- output dictionary with HDF5 variables h5 = {} #-- add variables to output file for key,attributes in attrib.items(): #-- Defining the HDF5 dataset variables for lat/lon h5[key] = fid.create_dataset(key, (file_lines,), data=dinput[key][:], dtype=dinput[key].dtype, compression='gzip') #-- add HDF5 variable attributes for att_name,att_val in attributes.items(): h5[key].attrs[att_name] = att_val #-- attach dimensions if key not in ('time',): for i,dim in enumerate(['time']): h5[key].dims[i].label = 'RECORD_SIZE' h5[key].dims[i].attach_scale(h5[dim]) #-- HDF5 file attributes fid.attrs['featureType'] = 'trajectory' fid.attrs['title'] = 'Tidal_correction_for_elevation_measurements' fid.attrs['summary'] = ('Tidal_correction_computed_at_elevation_' 'measurements_using_a_tidal_model_driver.') fid.attrs['project'] = 'NASA_Operation_IceBridge' fid.attrs['processing_level'] = '4' fid.attrs['date_created'] = time.strftime('%Y-%m-%d',time.localtime()) #-- add attributes for input file fid.attrs['elevation_file'] = os.path.basename(input_file) fid.attrs['tide_model'] = model.name #-- add geospatial and temporal attributes fid.attrs['geospatial_lat_min'] = dinput['lat'].min() fid.attrs['geospatial_lat_max'] = dinput['lat'].max() fid.attrs['geospatial_lon_min'] = dinput['lon'].min() fid.attrs['geospatial_lon_max'] = dinput['lon'].max() fid.attrs['geospatial_lat_units'] = "degrees_north" fid.attrs['geospatial_lon_units'] = "degrees_east" fid.attrs['geospatial_ellipsoid'] = "WGS84" fid.attrs['time_type'] = 'UTC' #-- convert start/end time from days since 1992-01-01 into Julian days time_range = np.array([np.min(t),np.max(t)]) time_julian = 2400000.5 + pyTMD.time.convert_delta_time(time_range, epoch1=(1992,1,1,0,0,0), epoch2=(1858,11,17,0,0,0), scale=1.0) #-- convert to calendar date cal = pyTMD.time.convert_julian(time_julian,ASTYPE=int) #-- add attributes with measurement date start, end and duration args = (cal['hour'][0],cal['minute'][0],cal['second'][0]) fid.attrs['RangeBeginningTime'] = '{0:02d}:{1:02d}:{2:02d}'.format(*args) args = (cal['hour'][-1],cal['minute'][-1],cal['second'][-1]) fid.attrs['RangeEndingTime'] = '{0:02d}:{1:02d}:{2:02d}'.format(*args) args = (cal['year'][0],cal['month'][0],cal['day'][0]) fid.attrs['RangeBeginningDate'] = '{0:4d}-{1:02d}-{2:02d}'.format(*args) args = (cal['year'][-1],cal['month'][-1],cal['day'][-1]) fid.attrs['RangeEndingDate'] = '{0:4d}-{1:02d}-{2:02d}'.format(*args) duration = np.round(time_julian[-1]*86400.0 - time_julian[0]*86400.0) fid.attrs['DurationTimeSeconds'] = '{0:0.0f}'.format(duration) #-- close the output HDF5 dataset fid.close() #-- change the permissions level to MODE os.chmod(os.path.join(DIRECTORY,FILENAME), MODE)
def compute_LPET_elevations(input_file, output_file, FORMAT='csv', VARIABLES=['time','lat','lon','data'], TIME_UNITS='days since 1858-11-17T00:00:00', PROJECTION='4326', VERBOSE=False, MODE=0o775): #-- output netCDF4 and HDF5 file attributes #-- will be added to YAML header in csv files attrib = {} #-- latitude attrib['lat'] = {} attrib['lat']['long_name'] = 'Latitude' attrib['lat']['units'] = 'Degrees_North' #-- longitude attrib['lon'] = {} attrib['lon']['long_name'] = 'Longitude' attrib['lon']['units'] = 'Degrees_East' #-- long-period equilibrium tides attrib['tide_lpe'] = {} attrib['tide_lpe']['long_name'] = 'Equilibrium_Tide' attrib['tide_lpe']['description'] = ('Long-period_equilibrium_tidal_' 'elevation_from_the_summation_of_fifteen_tidal_spectral_lines') attrib['tide_lpe']['reference'] = ('https://doi.org/10.1111/' 'j.1365-246X.1973.tb03420.x') attrib['tide_lpe']['units'] = 'meters' #-- time attrib['time'] = {} attrib['time']['long_name'] = 'Time' attrib['time']['units'] = 'days since 1992-01-01T00:00:00' attrib['time']['calendar'] = 'standard' #-- read input file to extract time, spatial coordinates and data if (FORMAT == 'csv'): dinput = pyTMD.spatial.from_ascii(input_file, columns=VARIABLES, header=0, verbose=VERBOSE) elif (FORMAT == 'netCDF4'): dinput = pyTMD.spatial.from_netCDF4(input_file, timename=VARIABLES[0], xname=VARIABLES[2], yname=VARIABLES[1], varname=VARIABLES[3], verbose=VERBOSE) elif (FORMAT == 'HDF5'): dinput = pyTMD.spatial.from_HDF5(input_file, timename=VARIABLES[0], xname=VARIABLES[2], yname=VARIABLES[1], varname=VARIABLES[3], verbose=VERBOSE) #-- converting x,y from projection to latitude/longitude #-- could try to extract projection attributes from netCDF4 and HDF5 files try: crs1 = pyproj.CRS.from_string("epsg:{0:d}".format(int(PROJECTION))) except (ValueError,pyproj.exceptions.CRSError): crs1 = pyproj.CRS.from_string(PROJECTION) crs2 = pyproj.CRS.from_string("epsg:{0:d}".format(4326)) transformer = pyproj.Transformer.from_crs(crs1, crs2, always_xy=True) lon,lat = transformer.transform(dinput['x'].flatten(),dinput['y'].flatten()) #-- extract time units from netCDF4 and HDF5 attributes or from TIME_UNITS try: time_string = dinput['attributes']['time']['units'] except (TypeError, KeyError): epoch1,to_secs = pyTMD.time.parse_date_string(TIME_UNITS) else: epoch1,to_secs = pyTMD.time.parse_date_string(time_string) #-- convert time from units to days since 1992-01-01T00:00:00 tide_time = pyTMD.time.convert_delta_time(to_secs*dinput['time'].flatten(), epoch1=epoch1, epoch2=(1992,1,1,0,0,0), scale=1.0/86400.0) #-- interpolate delta times from calendar dates to tide time delta_file = get_data_path(['data','merged_deltat.data']) deltat = calc_delta_time(delta_file, tide_time) #-- predict long-period equilibrium tides at time tide_lpe = compute_equilibrium_tide(tide_time + deltat, lat) #-- output to file output = dict(time=tide_time,lon=lon,lat=lat,tide_lpe=tide_lpe) if (FORMAT == 'csv'): pyTMD.spatial.to_ascii(output, attrib, output_file, delimiter=',', columns=['time','lat','lon','tide_lpe'], verbose=VERBOSE) elif (FORMAT == 'netCDF4'): pyTMD.spatial.to_netCDF4(output, attrib, output_file, verbose=VERBOSE) elif (FORMAT == 'HDF5'): pyTMD.spatial.to_HDF5(output, attrib, output_file, verbose=VERBOSE) #-- change the permissions level to MODE os.chmod(output_file, MODE)
def compute_tides_ICESat(tide_dir, INPUT_FILE, TIDE_MODEL=None, ATLAS_FORMAT=None, GZIP=True, DEFINITION_FILE=None, METHOD='spline', EXTRAPOLATE=False, CUTOFF=None, VERBOSE=False, MODE=0o775): #-- create logger for verbosity level loglevel = logging.INFO if VERBOSE else logging.CRITICAL logger = pyTMD.utilities.build_logger('pytmd',level=loglevel) #-- get parameters for tide model if DEFINITION_FILE is not None: model = pyTMD.model(tide_dir).from_file(DEFINITION_FILE) else: model = pyTMD.model(tide_dir, format=ATLAS_FORMAT, compressed=GZIP).elevation(TIDE_MODEL) #-- get directory from INPUT_FILE logger.info('{0} -->'.format(INPUT_FILE)) DIRECTORY = os.path.dirname(INPUT_FILE) #-- compile regular expression operator for extracting information from file rx = re.compile((r'GLAH(\d{2})_(\d{3})_(\d{1})(\d{1})(\d{2})_(\d{3})_' r'(\d{4})_(\d{1})_(\d{2})_(\d{4})\.H5'), re.VERBOSE) #-- extract parameters from ICESat/GLAS HDF5 file name #-- PRD: Product number (01, 05, 06, 12, 13, 14, or 15) #-- RL: Release number for process that created the product = 634 #-- RGTP: Repeat ground-track phase (1=8-day, 2=91-day, 3=transfer orbit) #-- ORB: Reference orbit number (starts at 1 and increments each time a #-- new reference orbit ground track file is obtained.) #-- INST: Instance number (increments every time the satellite enters a #-- different reference orbit) #-- CYCL: Cycle of reference orbit for this phase #-- TRK: Track within reference orbit #-- SEG: Segment of orbit #-- GRAN: Granule version number #-- TYPE: File type try: PRD,RL,RGTP,ORB,INST,CYCL,TRK,SEG,GRAN,TYPE = rx.findall(INPUT_FILE).pop() except: #-- output tide HDF5 file (generic) fileBasename,fileExtension = os.path.splitext(INPUT_FILE) args = (fileBasename,model.name,fileExtension) OUTPUT_FILE = '{0}_{1}_TIDES{2}'.format(*args) else: #-- output tide HDF5 file for NSIDC granules args = (PRD,RL,model.name,RGTP,ORB,INST,CYCL,TRK,SEG,GRAN,TYPE) file_format = 'GLAH{0}_{1}_{2}_TIDES_{3}{4}{5}_{6}_{7}_{8}_{9}_{10}.h5' OUTPUT_FILE = file_format.format(*args) #-- read GLAH12 HDF5 file fileID = h5py.File(INPUT_FILE,'r') n_40HZ, = fileID['Data_40HZ']['Time']['i_rec_ndx'].shape #-- get variables and attributes rec_ndx_40HZ = fileID['Data_40HZ']['Time']['i_rec_ndx'][:].copy() #-- seconds since 2000-01-01 12:00:00 UTC (J2000) DS_UTCTime_40HZ = fileID['Data_40HZ']['DS_UTCTime_40'][:].copy() #-- Latitude (degrees North) lat_TPX = fileID['Data_40HZ']['Geolocation']['d_lat'][:].copy() #-- Longitude (degrees East) lon_40HZ = fileID['Data_40HZ']['Geolocation']['d_lon'][:].copy() #-- Elevation (height above TOPEX/Poseidon ellipsoid in meters) elev_TPX = fileID['Data_40HZ']['Elevation_Surfaces']['d_elev'][:].copy() fv = fileID['Data_40HZ']['Elevation_Surfaces']['d_elev'].attrs['_FillValue'] #-- semimajor axis (a) and flattening (f) for TP and WGS84 ellipsoids atop,ftop = (6378136.3,1.0/298.257) awgs,fwgs = (6378137.0,1.0/298.257223563) #-- convert from Topex/Poseidon to WGS84 Ellipsoids lat_40HZ,elev_40HZ = pyTMD.spatial.convert_ellipsoid(lat_TPX, elev_TPX, atop, ftop, awgs, fwgs, eps=1e-12, itmax=10) #-- convert time from J2000 to days relative to Jan 1, 1992 (48622mjd) #-- J2000: seconds since 2000-01-01 12:00:00 UTC tide_time = pyTMD.time.convert_delta_time(DS_UTCTime_40HZ, epoch1=(2000,1,1,12,0,0), epoch2=(1992,1,1,0,0,0), scale=1.0/86400.0) #-- delta time (TT - UT1) file delta_file = pyTMD.utilities.get_data_path(['data','merged_deltat.data']) #-- read tidal constants and interpolate to grid points if model.format in ('OTIS','ATLAS'): amp,ph,D,c = extract_tidal_constants(lon_40HZ, lat_40HZ, model.grid_file, model.model_file, model.projection, TYPE=TYPE, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, GRID=model.format) deltat = np.zeros_like(tide_time) elif (model.format == 'netcdf'): amp,ph,D,c = extract_netcdf_constants(lon_40HZ, lat_40HZ, model.grid_file, model.model_file, TYPE=TYPE, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) deltat = np.zeros_like(tide_time) elif (model.format == 'GOT'): amp,ph,c = extract_GOT_constants(lon_40HZ, lat_40HZ, model.model_file, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, tide_time) elif (model.format == 'FES'): amp,ph = extract_FES_constants(lon_40HZ, lat_40HZ, model.model_file, TYPE=TYPE, VERSION=model.version, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) #-- available model constituents c = model.constituents #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, tide_time) #-- calculate complex phase in radians for Euler's cph = -1j*ph*np.pi/180.0 #-- calculate constituent oscillation hc = amp*np.exp(cph) #-- predict tidal elevations at time and infer minor corrections tide = np.ma.empty((n_40HZ),fill_value=fv) tide.mask = np.any(hc.mask,axis=1) tide.data[:] = predict_tide_drift(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model.format) minor = infer_minor_corrections(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model.format) tide.data[:] += minor.data[:] #-- replace masked and nan values with fill value invalid, = np.nonzero(np.isnan(tide.data) | tide.mask) tide.data[invalid] = tide.fill_value tide.mask[invalid] = True #-- copy variables for outputting to HDF5 file IS_gla12_tide = dict(Data_40HZ={}) IS_gla12_fill = dict(Data_40HZ={}) IS_gla12_tide_attrs = dict(Data_40HZ={}) #-- copy global file attributes of interest global_attribute_list = ['featureType','title','comment','summary','license', 'references','AccessConstraints','CitationforExternalPublication', 'contributor_role','contributor_name','creator_name','creator_email', 'publisher_name','publisher_email','publisher_url','platform','instrument', 'processing_level','date_created','spatial_coverage_type','history', 'keywords','keywords_vocabulary','naming_authority','project','time_type', 'date_type','time_coverage_start','time_coverage_end', 'time_coverage_duration','source','HDFVersion','identifier_product_type', 'identifier_product_format_version','Conventions','institution', 'ReprocessingPlanned','ReprocessingActual','LocalGranuleID', 'ProductionDateTime','LocalVersionID','PGEVersion','OrbitNumber', 'StartOrbitNumber','StopOrbitNumber','EquatorCrossingLongitude', 'EquatorCrossingTime','EquatorCrossingDate','ShortName','VersionID', 'InputPointer','RangeBeginningTime','RangeEndingTime','RangeBeginningDate', 'RangeEndingDate','PercentGroundHit','OrbitQuality','Cycle','Track', 'Instrument_State','Timing_Bias','ReferenceOrbit','SP_ICE_PATH_NO', 'SP_ICE_GLAS_StartBlock','SP_ICE_GLAS_EndBlock','Instance','Range_Bias', 'Instrument_State_Date','Instrument_State_Time','Range_Bias_Date', 'Range_Bias_Time','Timing_Bias_Date','Timing_Bias_Time', 'identifier_product_doi','identifier_file_uuid', 'identifier_product_doi_authority'] for att in global_attribute_list: IS_gla12_tide_attrs[att] = fileID.attrs[att] #-- copy ICESat campaign name from ancillary data IS_gla12_tide_attrs['Campaign'] = fileID['ANCILLARY_DATA'].attrs['Campaign'] #-- add attributes for input GLA12 file IS_gla12_tide_attrs['input_files'] = os.path.basename(INPUT_FILE) #-- update geospatial ranges for ellipsoid IS_gla12_tide_attrs['geospatial_lat_min'] = np.min(lat_40HZ) IS_gla12_tide_attrs['geospatial_lat_max'] = np.max(lat_40HZ) IS_gla12_tide_attrs['geospatial_lon_min'] = np.min(lon_40HZ) IS_gla12_tide_attrs['geospatial_lon_max'] = np.max(lon_40HZ) IS_gla12_tide_attrs['geospatial_lat_units'] = "degrees_north" IS_gla12_tide_attrs['geospatial_lon_units'] = "degrees_east" IS_gla12_tide_attrs['geospatial_ellipsoid'] = "WGS84" #-- copy 40Hz group attributes for att_name,att_val in fileID['Data_40HZ'].attrs.items(): IS_gla12_tide_attrs['Data_40HZ'][att_name] = att_val #-- copy attributes for time, geolocation and geophysical groups for var in ['Time','Geolocation','Geophysical']: IS_gla12_tide['Data_40HZ'][var] = {} IS_gla12_fill['Data_40HZ'][var] = {} IS_gla12_tide_attrs['Data_40HZ'][var] = {} for att_name,att_val in fileID['Data_40HZ'][var].attrs.items(): IS_gla12_tide_attrs['Data_40HZ'][var][att_name] = att_val #-- J2000 time IS_gla12_tide['Data_40HZ']['DS_UTCTime_40'] = DS_UTCTime_40HZ IS_gla12_fill['Data_40HZ']['DS_UTCTime_40'] = None IS_gla12_tide_attrs['Data_40HZ']['DS_UTCTime_40'] = {} for att_name,att_val in fileID['Data_40HZ']['DS_UTCTime_40'].attrs.items(): if att_name not in ('DIMENSION_LIST','CLASS','NAME'): IS_gla12_tide_attrs['Data_40HZ']['DS_UTCTime_40'][att_name] = att_val #-- record IS_gla12_tide['Data_40HZ']['Time']['i_rec_ndx'] = rec_ndx_40HZ IS_gla12_fill['Data_40HZ']['Time']['i_rec_ndx'] = None IS_gla12_tide_attrs['Data_40HZ']['Time']['i_rec_ndx'] = {} IS_gla12_tide_attrs['Data_40HZ']['Time']['i_rec_ndx']['coordinates'] = \ "../DS_UTCTime_40" for att_name,att_val in fileID['Data_40HZ']['Time']['i_rec_ndx'].attrs.items(): if att_name not in ('DIMENSION_LIST','CLASS','NAME'): IS_gla12_tide_attrs['Data_40HZ']['Time']['i_rec_ndx'][att_name] = att_val #-- latitude IS_gla12_tide['Data_40HZ']['Geolocation']['d_lat'] = lat_40HZ IS_gla12_fill['Data_40HZ']['Geolocation']['d_lat'] = None IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lat'] = {} IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lat']['coordinates'] = \ "../DS_UTCTime_40" for att_name,att_val in fileID['Data_40HZ']['Geolocation']['d_lat'].attrs.items(): if att_name not in ('DIMENSION_LIST','CLASS','NAME'): IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lat'][att_name] = att_val #-- longitude IS_gla12_tide['Data_40HZ']['Geolocation']['d_lon'] = lon_40HZ IS_gla12_fill['Data_40HZ']['Geolocation']['d_lon'] = None IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lon'] = {} IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lon']['coordinates'] = \ "../DS_UTCTime_40" for att_name,att_val in fileID['Data_40HZ']['Geolocation']['d_lon'].attrs.items(): if att_name not in ('DIMENSION_LIST','CLASS','NAME'): IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lon'][att_name] = att_val #-- geophysical variables #-- computed tide IS_gla12_tide['Data_40HZ']['Geophysical'][model.gla12] = tide IS_gla12_fill['Data_40HZ']['Geophysical'][model.gla12] = tide.fill_value IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][model.gla12] = {} IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][model.gla12]['units'] = "meters" IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][model.gla12]['long_name'] = model.long_name IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][model.gla12]['description'] = model.description IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][model.gla12]['source'] = model.name IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][model.gla12]['reference'] = model.reference IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][model.gla12]['coordinates'] = \ "../DS_UTCTime_40" #-- close the input HDF5 file fileID.close() #-- print file information logger.info('\t{0}'.format(OUTPUT_FILE)) HDF5_GLA12_tide_write(IS_gla12_tide, IS_gla12_tide_attrs, FILENAME=os.path.join(DIRECTORY,OUTPUT_FILE), FILL_VALUE=IS_gla12_fill, CLOBBER=True) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY,OUTPUT_FILE), MODE)
def compute_tides_ICESat2(tide_dir, FILE, TIDE_MODEL=None, METHOD='spline', EXTRAPOLATE=False, VERBOSE=False, MODE=0o775): #-- select between tide models if (TIDE_MODEL == 'CATS0201'): grid_file = os.path.join(tide_dir, 'cats0201_tmd', 'grid_CATS') model_file = os.path.join(tide_dir, 'cats0201_tmd', 'h0_CATS02_01') reference = 'https://mail.esr.org/polar_tide_models/Model_CATS0201.html' variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'CATS2008'): grid_file = os.path.join(tide_dir, 'CATS2008', 'grid_CATS2008') model_file = os.path.join(tide_dir, 'CATS2008', 'hf.CATS2008.out') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = 'CATS2008' TYPE = 'z' elif (TIDE_MODEL == 'CATS2008_load'): grid_file = os.path.join(tide_dir, 'CATS2008a_SPOTL_Load', 'grid_CATS2008a_opt') model_file = os.path.join(tide_dir, 'CATS2008a_SPOTL_Load', 'h_CATS2008a_SPOTL_load') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') variable = 'tide_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'OTIS' EPSG = 'CATS2008' TYPE = 'z' elif (TIDE_MODEL == 'TPXO9-atlas'): model_directory = os.path.join(tide_dir, 'TPXO9_atlas') grid_file = 'grid_tpxo9_atlas.nc.gz' model_files = [ 'h_q1_tpxo9_atlas_30.nc.gz', 'h_o1_tpxo9_atlas_30.nc.gz', 'h_p1_tpxo9_atlas_30.nc.gz', 'h_k1_tpxo9_atlas_30.nc.gz', 'h_n2_tpxo9_atlas_30.nc.gz', 'h_m2_tpxo9_atlas_30.nc.gz', 'h_s2_tpxo9_atlas_30.nc.gz', 'h_k2_tpxo9_atlas_30.nc.gz', 'h_m4_tpxo9_atlas_30.nc.gz', 'h_ms4_tpxo9_atlas_30.nc.gz', 'h_mn4_tpxo9_atlas_30.nc.gz', 'h_2n2_tpxo9_atlas_30.nc.gz' ] reference = 'http://volkov.oce.orst.edu/tides/tpxo9_atlas.html' variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'netcdf' TYPE = 'z' SCALE = 1.0 / 1000.0 elif (TIDE_MODEL == 'TPXO9-atlas-v2'): model_directory = os.path.join(tide_dir, 'TPXO9_atlas_v2') grid_file = 'grid_tpxo9_atlas_30_v2.nc.gz' model_files = [ 'h_q1_tpxo9_atlas_30_v2.nc.gz', 'h_o1_tpxo9_atlas_30_v2.nc.gz', 'h_p1_tpxo9_atlas_30_v2.nc.gz', 'h_k1_tpxo9_atlas_30_v2.nc.gz', 'h_n2_tpxo9_atlas_30_v2.nc.gz', 'h_m2_tpxo9_atlas_30_v2.nc.gz', 'h_s2_tpxo9_atlas_30_v2.nc.gz', 'h_k2_tpxo9_atlas_30_v2.nc.gz', 'h_m4_tpxo9_atlas_30_v2.nc.gz', 'h_ms4_tpxo9_atlas_30_v2.nc.gz', 'h_mn4_tpxo9_atlas_30_v2.nc.gz', 'h_2n2_tpxo9_atlas_30_v2.nc.gz' ] reference = 'https://www.tpxo.net/global/tpxo9-atlas' variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'netcdf' TYPE = 'z' SCALE = 1.0 / 1000.0 elif (TIDE_MODEL == 'TPXO9-atlas-v3'): model_directory = os.path.join(tide_dir, 'TPXO9_atlas_v3') grid_file = 'grid_tpxo9_atlas_30_v3.nc.gz' model_files = [ 'h_q1_tpxo9_atlas_30_v3.nc.gz', 'h_o1_tpxo9_atlas_30_v3.nc.gz', 'h_p1_tpxo9_atlas_30_v3.nc.gz', 'h_k1_tpxo9_atlas_30_v3.nc.gz', 'h_n2_tpxo9_atlas_30_v3.nc.gz', 'h_m2_tpxo9_atlas_30_v3.nc.gz', 'h_s2_tpxo9_atlas_30_v3.nc.gz', 'h_k2_tpxo9_atlas_30_v3.nc.gz', 'h_m4_tpxo9_atlas_30_v3.nc.gz', 'h_ms4_tpxo9_atlas_30_v3.nc.gz', 'h_mn4_tpxo9_atlas_30_v3.nc.gz', 'h_2n2_tpxo9_atlas_30_v3.nc.gz', 'h_mf_tpxo9_atlas_30_v3.nc.gz', 'h_mm_tpxo9_atlas_30_v3.nc.gz' ] reference = 'https://www.tpxo.net/global/tpxo9-atlas' variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'netcdf' TYPE = 'z' SCALE = 1.0 / 1000.0 elif (TIDE_MODEL == 'TPXO9.1'): grid_file = os.path.join(tide_dir, 'TPXO9.1', 'DATA', 'grid_tpxo9') model_file = os.path.join(tide_dir, 'TPXO9.1', 'DATA', 'h_tpxo9.v1') reference = 'http://volkov.oce.orst.edu/tides/global.html' variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO8-atlas'): grid_file = os.path.join(tide_dir, 'tpxo8_atlas', 'grid_tpxo8atlas_30_v1') model_file = os.path.join(tide_dir, 'tpxo8_atlas', 'hf.tpxo8_atlas_30_v1') reference = 'http://volkov.oce.orst.edu/tides/tpxo8_atlas.html' variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'ATLAS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO7.2'): grid_file = os.path.join(tide_dir, 'TPXO7.2_tmd', 'grid_tpxo7.2') model_file = os.path.join(tide_dir, 'TPXO7.2_tmd', 'h_tpxo7.2') reference = 'http://volkov.oce.orst.edu/tides/global.html' variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO7.2_load'): grid_file = os.path.join(tide_dir, 'TPXO7.2_load', 'grid_tpxo6.2') model_file = os.path.join(tide_dir, 'TPXO7.2_load', 'h_tpxo7.2_load') reference = 'http://volkov.oce.orst.edu/tides/global.html' variable = 'tide_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'AODTM-5'): grid_file = os.path.join(tide_dir, 'aodtm5_tmd', 'grid_Arc5km') model_file = os.path.join(tide_dir, 'aodtm5_tmd', 'h0_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aodtm-5/') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'AOTIM-5'): grid_file = os.path.join(tide_dir, 'aotim5_tmd', 'grid_Arc5km') model_file = os.path.join(tide_dir, 'aotim5_tmd', 'h_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'AOTIM-5-2018'): grid_file = os.path.join(tide_dir, 'Arc5km2018', 'grid_Arc5km2018') model_file = os.path.join(tide_dir, 'Arc5km2018', 'h_Arc5km2018') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'GOT4.7'): model_directory = os.path.join(tide_dir, 'GOT4.7', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'GOT' SCALE = 1.0 / 100.0 elif (TIDE_MODEL == 'GOT4.7_load'): model_directory = os.path.join(tide_dir, 'GOT4.7', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'tide_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'GOT' SCALE = 1.0 / 1000.0 elif (TIDE_MODEL == 'GOT4.8'): model_directory = os.path.join(tide_dir, 'got4.8', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'GOT' SCALE = 1.0 / 100.0 elif (TIDE_MODEL == 'GOT4.8_load'): model_directory = os.path.join(tide_dir, 'got4.8', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'tide_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'GOT' SCALE = 1.0 / 1000.0 elif (TIDE_MODEL == 'GOT4.10'): model_directory = os.path.join(tide_dir, 'GOT4.10c', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'GOT' SCALE = 1.0 / 100.0 elif (TIDE_MODEL == 'GOT4.10_load'): model_directory = os.path.join(tide_dir, 'GOT4.10c', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'tide_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'GOT' SCALE = 1.0 / 1000.0 elif (TIDE_MODEL == 'FES2014'): model_directory = os.path.join(tide_dir, 'fes2014', 'ocean_tide') model_files = [ '2n2.nc.gz', 'eps2.nc.gz', 'j1.nc.gz', 'k1.nc.gz', 'k2.nc.gz', 'l2.nc.gz', 'la2.nc.gz', 'm2.nc.gz', 'm3.nc.gz', 'm4.nc.gz', 'm6.nc.gz', 'm8.nc.gz', 'mf.nc.gz', 'mks2.nc.gz', 'mm.nc.gz', 'mn4.nc.gz', 'ms4.nc.gz', 'msf.nc.gz', 'msqm.nc.gz', 'mtm.nc.gz', 'mu2.nc.gz', 'n2.nc.gz', 'n4.nc.gz', 'nu2.nc.gz', 'o1.nc.gz', 'p1.nc.gz', 'q1.nc.gz', 'r2.nc.gz', 's1.nc.gz', 's2.nc.gz', 's4.nc.gz', 'sa.nc.gz', 'ssa.nc.gz', 't2.nc.gz' ] c = [ '2n2', 'eps2', 'j1', 'k1', 'k2', 'l2', 'lambda2', 'm2', 'm3', 'm4', 'm6', 'm8', 'mf', 'mks2', 'mm', 'mn4', 'ms4', 'msf', 'msqm', 'mtm', 'mu2', 'n2', 'n4', 'nu2', 'o1', 'p1', 'q1', 'r2', 's1', 's2', 's4', 'sa', 'ssa', 't2' ] reference = ('https://www.aviso.altimetry.fr/en/data/products' 'auxiliary-products/global-tide-fes.html') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'FES' TYPE = 'z' SCALE = 1.0 / 100.0 elif (TIDE_MODEL == 'FES2014_load'): model_directory = os.path.join(tide_dir, 'fes2014', 'load_tide') model_files = [ '2n2.nc.gz', 'eps2.nc.gz', 'j1.nc.gz', 'k1.nc.gz', 'k2.nc.gz', 'l2.nc.gz', 'la2.nc.gz', 'm2.nc.gz', 'm3.nc.gz', 'm4.nc.gz', 'm6.nc.gz', 'm8.nc.gz', 'mf.nc.gz', 'mks2.nc.gz', 'mm.nc.gz', 'mn4.nc.gz', 'ms4.nc.gz', 'msf.nc.gz', 'msqm.nc.gz', 'mtm.nc.gz', 'mu2.nc.gz', 'n2.nc.gz', 'n4.nc.gz', 'nu2.nc.gz', 'o1.nc.gz', 'p1.nc.gz', 'q1.nc.gz', 'r2.nc.gz', 's1.nc.gz', 's2.nc.gz', 's4.nc.gz', 'sa.nc.gz', 'ssa.nc.gz', 't2.nc.gz' ] c = [ '2n2', 'eps2', 'j1', 'k1', 'k2', 'l2', 'lambda2', 'm2', 'm3', 'm4', 'm6', 'm8', 'mf', 'mks2', 'mm', 'mn4', 'ms4', 'msf', 'msqm', 'mtm', 'mu2', 'n2', 'n4', 'nu2', 'o1', 'p1', 'q1', 'r2', 's1', 's2', 's4', 'sa', 'ssa', 't2' ] reference = ('https://www.aviso.altimetry.fr/en/data/products' 'auxiliary-products/global-tide-fes.html') variable = 'tide_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'FES' TYPE = 'z' SCALE = 1.0 / 100.0 #-- read data from FILE print('{0} -->'.format(os.path.basename(FILE))) if VERBOSE else None IS2_atl11_mds, IS2_atl11_attrs, IS2_atl11_pairs = read_HDF5_ATL11( FILE, ATTRIBUTES=True) DIRECTORY = os.path.dirname(FILE) #-- extract parameters from ICESat-2 ATLAS HDF5 file name rx = re.compile(r'(processed_)?(ATL\d{2})_(\d{4})(\d{2})_(\d{2})(\d{2})_' r'(\d{3})_(\d{2})(.*?).h5$') SUB, PRD, TRK, GRAN, SCYC, ECYC, RL, VERS, AUX = rx.findall(FILE).pop() #-- number of GPS seconds between the GPS epoch #-- and ATLAS Standard Data Product (SDP) epoch atlas_sdp_gps_epoch = IS2_atl11_mds['ancillary_data'][ 'atlas_sdp_gps_epoch'] #-- copy variables for outputting to HDF5 file IS2_atl11_tide = {} IS2_atl11_fill = {} IS2_atl11_dims = {} IS2_atl11_tide_attrs = {} #-- number of GPS seconds between the GPS epoch (1980-01-06T00:00:00Z UTC) #-- and ATLAS Standard Data Product (SDP) epoch (2018-01-01T00:00:00Z UTC) #-- Add this value to delta time parameters to compute full gps_seconds IS2_atl11_tide['ancillary_data'] = {} IS2_atl11_tide_attrs['ancillary_data'] = {} for key in ['atlas_sdp_gps_epoch']: #-- get each HDF5 variable IS2_atl11_tide['ancillary_data'][key] = IS2_atl11_mds[ 'ancillary_data'][key] #-- Getting attributes of group and included variables IS2_atl11_tide_attrs['ancillary_data'][key] = {} for att_name, att_val in IS2_atl11_attrs['ancillary_data'][key].items( ): IS2_atl11_tide_attrs['ancillary_data'][key][att_name] = att_val #-- for each input beam pair within the file for ptx in sorted(IS2_atl11_pairs): #-- output data dictionaries for beam IS2_atl11_tide[ptx] = dict(cycle_stats={}) IS2_atl11_fill[ptx] = dict(cycle_stats={}) IS2_atl11_dims[ptx] = dict(cycle_stats={}) IS2_atl11_tide_attrs[ptx] = dict(cycle_stats={}) #-- number of average segments and number of included cycles invalid_time = IS2_atl11_attrs[ptx]['delta_time']['_FillValue'] n_points, n_cycles = IS2_atl11_mds[ptx]['delta_time'].shape #-- find valid average segments for beam pair fv = IS2_atl11_attrs[ptx]['h_corr']['_FillValue'] #-- convert time from ATLAS SDP to days relative to Jan 1, 1992 gps_seconds = atlas_sdp_gps_epoch + IS2_atl11_mds[ptx]['delta_time'] leap_seconds = pyTMD.time.count_leap_seconds(gps_seconds) tide_time = pyTMD.time.convert_delta_time(gps_seconds - leap_seconds, epoch1=(1980, 1, 6, 0, 0, 0), epoch2=(1992, 1, 1, 0, 0, 0), scale=1.0 / 86400.0) #-- read tidal constants and interpolate to grid points if model_format in ('OTIS', 'ATLAS'): amp, ph, D, c = extract_tidal_constants( IS2_atl11_mds[ptx]['longitude'], IS2_atl11_mds[ptx]['latitude'], grid_file, model_file, EPSG, TYPE=TYPE, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, GRID=model_format) deltat = np.zeros_like(tide_time) elif (model_format == 'netcdf'): amp, ph, D, c = extract_netcdf_constants( IS2_atl11_mds[ptx]['longitude'], IS2_atl11_mds[ptx]['latitude'], model_directory, grid_file, model_files, TYPE=TYPE, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=SCALE) deltat = np.zeros_like(tide_time) elif (model_format == 'GOT'): amp, ph = extract_GOT_constants(IS2_atl11_mds[ptx]['longitude'], IS2_atl11_mds[ptx]['latitude'], model_directory, model_files, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=SCALE) #-- interpolate delta times from calendar dates to tide time delta_file = pyTMD.utilities.get_data_path( ['data', 'merged_deltat.data']) deltat = calc_delta_time(delta_file, tide_time) elif (model_format == 'FES'): amp, ph = extract_FES_constants(IS2_atl11_mds[ptx]['longitude'], IS2_atl11_mds[ptx]['latitude'], model_directory, model_files, TYPE=TYPE, VERSION=TIDE_MODEL, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=SCALE) #-- interpolate delta times from calendar dates to tide time delta_file = pyTMD.utilities.get_data_path( ['data', 'merged_deltat.data']) deltat = calc_delta_time(delta_file, tide_time) #-- calculate complex phase in radians for Euler's cph = -1j * ph * np.pi / 180.0 #-- calculate constituent oscillation hc = amp * np.exp(cph) #-- allocate for each cycle tide = np.ma.empty((n_points, n_cycles), fill_value=fv) tide.mask = (IS2_atl11_mds[ptx]['delta_time'] == invalid_time) for cycle in range(n_cycles): #-- find valid time and spatial points for cycle tide.mask[:, cycle] |= np.any(hc.mask, axis=1) valid, = np.nonzero(~tide.mask[:, cycle]) #-- predict tidal elevations and infer minor corrections tide.data[valid, cycle] = predict_tide_drift(tide_time[valid, cycle], hc[valid, :], c, DELTAT=deltat[valid, cycle], CORRECTIONS=model_format) minor = infer_minor_corrections(tide_time[valid, cycle], hc[valid, :], c, DELTAT=deltat[valid, cycle], CORRECTIONS=model_format) tide.data[valid, cycle] += minor.data[:] #-- replace masked and nan values with fill value invalid = np.nonzero(np.isnan(tide.data) | tide.mask) tide.data[invalid] = tide.fill_value tide.mask[invalid] = True #-- group attributes for beam IS2_atl11_tide_attrs[ptx]['description'] = ( 'Contains the primary science parameters for this ' 'data set') IS2_atl11_tide_attrs[ptx]['beam_pair'] = IS2_atl11_attrs[ptx][ 'beam_pair'] IS2_atl11_tide_attrs[ptx]['ReferenceGroundTrack'] = IS2_atl11_attrs[ ptx]['ReferenceGroundTrack'] IS2_atl11_tide_attrs[ptx]['first_cycle'] = IS2_atl11_attrs[ptx][ 'first_cycle'] IS2_atl11_tide_attrs[ptx]['last_cycle'] = IS2_atl11_attrs[ptx][ 'last_cycle'] IS2_atl11_tide_attrs[ptx]['equatorial_radius'] = IS2_atl11_attrs[ptx][ 'equatorial_radius'] IS2_atl11_tide_attrs[ptx]['polar_radius'] = IS2_atl11_attrs[ptx][ 'polar_radius'] #-- geolocation, time and reference point #-- cycle_number IS2_atl11_tide[ptx]['cycle_number'] = IS2_atl11_mds[ptx][ 'cycle_number'].copy() IS2_atl11_fill[ptx]['cycle_number'] = None IS2_atl11_dims[ptx]['cycle_number'] = None IS2_atl11_tide_attrs[ptx]['cycle_number'] = {} IS2_atl11_tide_attrs[ptx]['cycle_number']['units'] = "1" IS2_atl11_tide_attrs[ptx]['cycle_number'][ 'long_name'] = "Orbital cycle number" IS2_atl11_tide_attrs[ptx]['cycle_number']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['cycle_number']['description'] = ( "Number of 91-day periods " "that have elapsed since ICESat-2 entered the science orbit. Each of the 1,387 " "reference ground track (RGTs) is targeted in the polar regions once " "every 91 days.") #-- delta time IS2_atl11_tide[ptx]['delta_time'] = IS2_atl11_mds[ptx][ 'delta_time'].copy() IS2_atl11_fill[ptx]['delta_time'] = IS2_atl11_attrs[ptx]['delta_time'][ '_FillValue'] IS2_atl11_dims[ptx]['delta_time'] = ['ref_pt', 'cycle_number'] IS2_atl11_tide_attrs[ptx]['delta_time'] = {} IS2_atl11_tide_attrs[ptx]['delta_time'][ 'units'] = "seconds since 2018-01-01" IS2_atl11_tide_attrs[ptx]['delta_time'][ 'long_name'] = "Elapsed GPS seconds" IS2_atl11_tide_attrs[ptx]['delta_time']['standard_name'] = "time" IS2_atl11_tide_attrs[ptx]['delta_time']['calendar'] = "standard" IS2_atl11_tide_attrs[ptx]['delta_time']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['delta_time']['description'] = ( "Number of GPS " "seconds since the ATLAS SDP epoch. The ATLAS Standard Data Products (SDP) epoch offset " "is defined within /ancillary_data/atlas_sdp_gps_epoch as the number of GPS seconds " "between the GPS epoch (1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP epoch. By " "adding the offset contained within atlas_sdp_gps_epoch to delta time parameters, the " "time in gps_seconds relative to the GPS epoch can be computed.") IS2_atl11_tide_attrs[ptx]['delta_time']['coordinates'] = \ "ref_pt cycle_number latitude longitude" #-- latitude IS2_atl11_tide[ptx]['latitude'] = IS2_atl11_mds[ptx]['latitude'].copy() IS2_atl11_fill[ptx]['latitude'] = IS2_atl11_attrs[ptx]['latitude'][ '_FillValue'] IS2_atl11_dims[ptx]['latitude'] = ['ref_pt'] IS2_atl11_tide_attrs[ptx]['latitude'] = {} IS2_atl11_tide_attrs[ptx]['latitude']['units'] = "degrees_north" IS2_atl11_tide_attrs[ptx]['latitude'][ 'contentType'] = "physicalMeasurement" IS2_atl11_tide_attrs[ptx]['latitude']['long_name'] = "Latitude" IS2_atl11_tide_attrs[ptx]['latitude']['standard_name'] = "latitude" IS2_atl11_tide_attrs[ptx]['latitude']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['latitude']['description'] = ( "Center latitude of " "selected segments") IS2_atl11_tide_attrs[ptx]['latitude']['valid_min'] = -90.0 IS2_atl11_tide_attrs[ptx]['latitude']['valid_max'] = 90.0 IS2_atl11_tide_attrs[ptx]['latitude']['coordinates'] = \ "ref_pt delta_time longitude" #-- longitude IS2_atl11_tide[ptx]['longitude'] = IS2_atl11_mds[ptx][ 'longitude'].copy() IS2_atl11_fill[ptx]['longitude'] = IS2_atl11_attrs[ptx]['longitude'][ '_FillValue'] IS2_atl11_dims[ptx]['longitude'] = ['ref_pt'] IS2_atl11_tide_attrs[ptx]['longitude'] = {} IS2_atl11_tide_attrs[ptx]['longitude']['units'] = "degrees_east" IS2_atl11_tide_attrs[ptx]['longitude'][ 'contentType'] = "physicalMeasurement" IS2_atl11_tide_attrs[ptx]['longitude']['long_name'] = "Longitude" IS2_atl11_tide_attrs[ptx]['longitude']['standard_name'] = "longitude" IS2_atl11_tide_attrs[ptx]['longitude']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['longitude']['description'] = ( "Center longitude of " "selected segments") IS2_atl11_tide_attrs[ptx]['longitude']['valid_min'] = -180.0 IS2_atl11_tide_attrs[ptx]['longitude']['valid_max'] = 180.0 IS2_atl11_tide_attrs[ptx]['longitude']['coordinates'] = \ "ref_pt delta_time latitude" #-- reference point IS2_atl11_tide[ptx]['ref_pt'] = IS2_atl11_mds[ptx]['ref_pt'].copy() IS2_atl11_fill[ptx]['ref_pt'] = None IS2_atl11_dims[ptx]['ref_pt'] = None IS2_atl11_tide_attrs[ptx]['ref_pt'] = {} IS2_atl11_tide_attrs[ptx]['ref_pt']['units'] = "1" IS2_atl11_tide_attrs[ptx]['ref_pt'][ 'contentType'] = "referenceInformation" IS2_atl11_tide_attrs[ptx]['ref_pt'][ 'long_name'] = "Reference point number" IS2_atl11_tide_attrs[ptx]['ref_pt']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['ref_pt']['description'] = ( "The reference point is the 7 digit segment_id " "number corresponding to the center of the ATL06 data used for each ATL11 point. These are " "sequential, starting with 1 for the first segment after an ascending equatorial crossing node." ) IS2_atl11_tide_attrs[ptx]['ref_pt']['coordinates'] = \ "delta_time latitude longitude" #-- cycle statistics variables IS2_atl11_tide_attrs[ptx]['cycle_stats']['Description'] = ( "The cycle_stats subgroup " "contains summary information about segments for each reference point, including " "the uncorrected mean heights for reference surfaces, blowing snow and cloud " "indicators, and geolocation and height misfit statistics.") IS2_atl11_tide_attrs[ptx]['cycle_stats']['data_rate'] = ( "Data within this group " "are stored at the average segment rate.") #-- computed tide IS2_atl11_tide[ptx]['cycle_stats'][variable] = tide IS2_atl11_fill[ptx]['cycle_stats'][variable] = tide.fill_value IS2_atl11_dims[ptx]['cycle_stats'][variable] = [ 'ref_pt', 'cycle_number' ] IS2_atl11_tide_attrs[ptx]['cycle_stats'][variable] = {} IS2_atl11_tide_attrs[ptx]['cycle_stats'][variable]['units'] = "meters" IS2_atl11_tide_attrs[ptx]['cycle_stats'][variable][ 'contentType'] = "referenceInformation" IS2_atl11_tide_attrs[ptx]['cycle_stats'][variable][ 'long_name'] = long_name IS2_atl11_tide_attrs[ptx]['cycle_stats'][variable][ 'description'] = description IS2_atl11_tide_attrs[ptx]['cycle_stats'][variable][ 'source'] = TIDE_MODEL IS2_atl11_tide_attrs[ptx]['cycle_stats'][variable][ 'reference'] = reference IS2_atl11_tide_attrs[ptx]['cycle_stats'][variable]['coordinates'] = \ "../ref_pt ../cycle_number ../delta_time ../latitude ../longitude" #-- output tidal HDF5 file args = (PRD, TIDE_MODEL, TRK, GRAN, SCYC, ECYC, RL, VERS, AUX) file_format = '{0}_{1}_TIDES_{2}{3}_{4}{5}_{6}_{7}{8}.h5' #-- print file information print('\t{0}'.format(file_format.format(*args))) if VERBOSE else None HDF5_ATL11_tide_write(IS2_atl11_tide, IS2_atl11_tide_attrs, CLOBBER=True, INPUT=os.path.basename(FILE), FILL_VALUE=IS2_atl11_fill, DIMENSIONS=IS2_atl11_dims, FILENAME=os.path.join(DIRECTORY, file_format.format(*args))) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY, file_format.format(*args)), MODE)
def compute_LPET_ICESat2(FILE, VERBOSE=False, MODE=0o775): #-- read data from FILE print('{0} -->'.format(os.path.basename(FILE))) if VERBOSE else None IS2_atl07_mds, IS2_atl07_attrs, IS2_atl07_beams = read_HDF5_ATL07( FILE, ATTRIBUTES=True) DIRECTORY = os.path.dirname(FILE) #-- extract parameters from ICESat-2 ATLAS HDF5 sea ice file name rx = re.compile( r'(processed_)?(ATL\d{2})-(\d{2})_(\d{4})(\d{2})(\d{2})' r'(\d{2})(\d{2})(\d{2})_(\d{4})(\d{2})(\d{2})_(\d{3})_(\d{2})(.*?).h5$' ) SUB, PRD, HEM, YY, MM, DD, HH, MN, SS, TRK, CYCL, SN, RL, VERS, AUX = rx.findall( FILE).pop() #-- number of GPS seconds between the GPS epoch #-- and ATLAS Standard Data Product (SDP) epoch atlas_sdp_gps_epoch = IS2_atl07_mds['ancillary_data'][ 'atlas_sdp_gps_epoch'] #-- copy variables for outputting to HDF5 file IS2_atl07_tide = {} IS2_atl07_fill = {} IS2_atl07_dims = {} IS2_atl07_tide_attrs = {} #-- number of GPS seconds between the GPS epoch (1980-01-06T00:00:00Z UTC) #-- and ATLAS Standard Data Product (SDP) epoch (2018-01-01T00:00:00Z UTC) #-- Add this value to delta time parameters to compute full gps_seconds IS2_atl07_tide['ancillary_data'] = {} IS2_atl07_tide_attrs['ancillary_data'] = {} for key in ['atlas_sdp_gps_epoch']: #-- get each HDF5 variable IS2_atl07_tide['ancillary_data'][key] = IS2_atl07_mds[ 'ancillary_data'][key] #-- Getting attributes of group and included variables IS2_atl07_tide_attrs['ancillary_data'][key] = {} for att_name, att_val in IS2_atl07_attrs['ancillary_data'][key].items( ): IS2_atl07_tide_attrs['ancillary_data'][key][att_name] = att_val #-- for each input beam within the file for gtx in sorted(IS2_atl07_beams): #-- output data dictionaries for beam IS2_atl07_tide[gtx] = dict(sea_ice_segments={}) IS2_atl07_fill[gtx] = dict(sea_ice_segments={}) IS2_atl07_dims[gtx] = dict(sea_ice_segments={}) IS2_atl07_tide_attrs[gtx] = dict(sea_ice_segments={}) #-- number of segments val = IS2_atl07_mds[gtx]['sea_ice_segments'] #-- convert time from ATLAS SDP to days relative to Jan 1, 1992 gps_seconds = atlas_sdp_gps_epoch + val['delta_time'] leap_seconds = pyTMD.time.count_leap_seconds(gps_seconds) tide_time = pyTMD.time.convert_delta_time(gps_seconds - leap_seconds, epoch1=(1980, 1, 6, 0, 0, 0), epoch2=(1992, 1, 1, 0, 0, 0), scale=1.0 / 86400.0) #-- interpolate delta times from calendar dates to tide time delta_file = get_data_path(['data', 'merged_deltat.data']) deltat = calc_delta_time(delta_file, tide_time) #-- predict long-period equilibrium tides at latitudes and time tide_lpe = compute_equilibrium_tide(tide_time + deltat, val['latitude']) #-- group attributes for beam IS2_atl07_tide_attrs[gtx]['Description'] = IS2_atl07_attrs[gtx][ 'Description'] IS2_atl07_tide_attrs[gtx]['atlas_pce'] = IS2_atl07_attrs[gtx][ 'atlas_pce'] IS2_atl07_tide_attrs[gtx]['atlas_beam_type'] = IS2_atl07_attrs[gtx][ 'atlas_beam_type'] IS2_atl07_tide_attrs[gtx]['groundtrack_id'] = IS2_atl07_attrs[gtx][ 'groundtrack_id'] IS2_atl07_tide_attrs[gtx]['atmosphere_profile'] = IS2_atl07_attrs[gtx][ 'atmosphere_profile'] IS2_atl07_tide_attrs[gtx]['atlas_spot_number'] = IS2_atl07_attrs[gtx][ 'atlas_spot_number'] IS2_atl07_tide_attrs[gtx]['sc_orientation'] = IS2_atl07_attrs[gtx][ 'sc_orientation'] #-- group attributes for sea_ice_segments IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['Description'] = ( "Top group for sea " "ice segments as computed by the ATBD algorithm.") IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['data_rate'] = ( "Data within this " "group are stored at the variable segment rate.") #-- geolocation, time and segment ID #-- delta time IS2_atl07_tide[gtx]['sea_ice_segments']['delta_time'] = val[ 'delta_time'].copy() IS2_atl07_fill[gtx]['sea_ice_segments']['delta_time'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['delta_time'] = None IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time'][ 'units'] = "seconds since 2018-01-01" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time'][ 'long_name'] = "Elapsed GPS seconds" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time'][ 'standard_name'] = "time" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time'][ 'source'] = "telemetry" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time'][ 'calendar'] = "standard" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time']['description'] = ( "Number of " "GPS seconds since the ATLAS SDP epoch. The ATLAS Standard Data Products (SDP) epoch " "offset is defined within /ancillary_data/atlas_sdp_gps_epoch as the number of GPS " "seconds between the GPS epoch (1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP " "epoch. By adding the offset contained within atlas_sdp_gps_epoch to delta time " "parameters, the time in gps_seconds relative to the GPS epoch can be computed." ) IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time']['coordinates'] = \ "height_segment_id latitude longitude" #-- latitude IS2_atl07_tide[gtx]['sea_ice_segments']['latitude'] = val[ 'latitude'].copy() IS2_atl07_fill[gtx]['sea_ice_segments']['latitude'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['latitude'] = ['delta_time'] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude'][ 'units'] = "degrees_north" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude'][ 'contentType'] = "physicalMeasurement" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude'][ 'long_name'] = "Latitude" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude'][ 'standard_name'] = "latitude" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude'][ 'description'] = ("Latitude of " "segment center") IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude'][ 'valid_min'] = -90.0 IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude'][ 'valid_max'] = 90.0 IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude']['coordinates'] = \ "height_segment_id delta_time longitude" #-- longitude IS2_atl07_tide[gtx]['sea_ice_segments']['longitude'] = val[ 'longitude'].copy() IS2_atl07_fill[gtx]['sea_ice_segments']['longitude'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['longitude'] = ['delta_time'] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude'][ 'units'] = "degrees_east" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude'][ 'contentType'] = "physicalMeasurement" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude'][ 'long_name'] = "Longitude" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude'][ 'standard_name'] = "longitude" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude'][ 'description'] = ("Longitude of " "segment center") IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude'][ 'valid_min'] = -180.0 IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude'][ 'valid_max'] = 180.0 IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude']['coordinates'] = \ "height_segment_id delta_time latitude" #-- segment ID IS2_atl07_tide[gtx]['sea_ice_segments']['height_segment_id'] = val[ 'height_segment_id'] IS2_atl07_fill[gtx]['sea_ice_segments']['height_segment_id'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['height_segment_id'] = [ 'delta_time' ] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['height_segment_id'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['height_segment_id'][ 'units'] = "1" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['height_segment_id'][ 'contentType'] = "referenceInformation" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['height_segment_id']['long_name'] = \ "Identifier of each height segment" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['height_segment_id']['description'] = \ "Identifier of each height segment" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['height_segment_id']['coordinates'] = \ "delta_time latitude longitude" #-- geolocation segment beginning IS2_atl07_tide[gtx]['sea_ice_segments']['geoseg_beg'] = val[ 'geoseg_beg'].copy() IS2_atl07_fill[gtx]['sea_ice_segments']['geoseg_beg'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['geoseg_beg'] = ['delta_time'] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_beg'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_beg'][ 'units'] = "1" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_beg'][ 'contentType'] = "referenceInformation" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_beg'][ 'long_name'] = "Beginning GEOSEG" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_beg']['description'] = \ "Geolocation segment (geoseg) ID associated with the first photon used in this sea ice segment" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_beg']['coordinates'] = \ "height_segment_id delta_time latitude longitude" #-- geolocation segment ending IS2_atl07_tide[gtx]['sea_ice_segments']['geoseg_end'] = val[ 'geoseg_end'].copy() IS2_atl07_fill[gtx]['sea_ice_segments']['geoseg_end'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['geoseg_end'] = ['delta_time'] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_end'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_end'][ 'units'] = "1" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_end'][ 'contentType'] = "referenceInformation" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_end'][ 'long_name'] = "Ending GEOSEG" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_end']['description'] = \ "Geolocation segment (geoseg) ID associated with the last photon used in this sea ice segment" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_end']['coordinates'] = \ "height_segment_id delta_time latitude longitude" #-- along track distance IS2_atl07_tide[gtx]['sea_ice_segments']['seg_dist_x'] = val[ 'seg_dist_x'].copy() IS2_atl07_fill[gtx]['sea_ice_segments']['seg_dist_x'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['seg_dist_x'] = ['delta_time'] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['seg_dist_x'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['seg_dist_x'][ 'units'] = "meters" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['seg_dist_x'][ 'contentType'] = "referenceInformation" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['seg_dist_x'][ 'long_name'] = "Along track distance" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['seg_dist_x']['description'] = \ "Along-track distance from the equator crossing to the segment center." IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['seg_dist_x']['coordinates'] = \ "height_segment_id delta_time latitude longitude" #-- geophysical variables IS2_atl07_tide[gtx]['sea_ice_segments']['geophysical'] = {} IS2_atl07_fill[gtx]['sea_ice_segments']['geophysical'] = {} IS2_atl07_dims[gtx]['sea_ice_segments']['geophysical'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][ 'Description'] = ( "Contains geophysical " "parameters and corrections used to correct photon heights for geophysical effects, such as tides." ) IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][ 'data_rate'] = ("Data within this group " "are stored at the sea_ice_height segment rate.") #-- computed long-period equilibrium tide IS2_atl07_tide[gtx]['sea_ice_segments']['geophysical'][ 'height_segment_lpe'] = tide_lpe IS2_atl07_fill[gtx]['sea_ice_segments']['geophysical'][ 'height_segment_lpe'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['geophysical'][ 'height_segment_lpe'] = ['delta_time'] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][ 'height_segment_lpe'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][ 'height_segment_lpe']['units'] = "meters" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][ 'height_segment_lpe']['contentType'] = "referenceInformation" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical']['height_segment_lpe']['long_name'] = \ "Long Period Equilibrium Tide" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][ 'height_segment_lpe']['description'] = ( "Long-period " "equilibrium tidal elevation from the summation of fifteen tidal spectral lines" ) IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical']['height_segment_lpe']['reference'] = \ "https://doi.org/10.1111/j.1365-246X.1973.tb03420.x" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical']['height_segment_lpe']['coordinates'] = \ "../height_segment_id ../delta_time ../latitude ../longitude" #-- output equilibrium tide HDF5 file args = (PRD, HEM, YY, MM, DD, HH, MN, SS, TRK, CYCL, SN, RL, VERS, AUX) ff = '{0}-{1}_LPET_{2}{3}{4}{5}{6}{7}_{8}{9}{10}_{11}_{12}{13}.h5' #-- print file information print('\t{0}'.format(ff.format(*args))) if VERBOSE else None HDF5_ATL07_tide_write(IS2_atl07_tide, IS2_atl07_tide_attrs, CLOBBER=True, INPUT=os.path.basename(FILE), FILL_VALUE=IS2_atl07_fill, DIMENSIONS=IS2_atl07_dims, FILENAME=os.path.join(DIRECTORY, ff.format(*args))) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY, ff.format(*args)), MODE)
def compute_LPET_ICESat2(INPUT_FILE, VERBOSE=False, MODE=0o775): #-- read data from input file print('{0} -->'.format(os.path.basename(INPUT_FILE))) if VERBOSE else None IS2_atl06_mds, IS2_atl06_attrs, IS2_atl06_beams = read_HDF5_ATL06( INPUT_FILE, ATTRIBUTES=True) DIRECTORY = os.path.dirname(INPUT_FILE) #-- extract parameters from ICESat-2 ATLAS HDF5 file name rx = re.compile( r'(processed_)?(ATL\d{2})_(\d{4})(\d{2})(\d{2})(\d{2})' r'(\d{2})(\d{2})_(\d{4})(\d{2})(\d{2})_(\d{3})_(\d{2})(.*?).h5$') try: SUB, PRD, YY, MM, DD, HH, MN, SS, TRK, CYCL, GRAN, RL, VERS, AUX = rx.findall( INPUT_FILE).pop() except: #-- output long-period equilibrium tide HDF5 file (generic) fileBasename, fileExtension = os.path.splitext(INPUT_FILE) OUTPUT_FILE = '{0}_{1}{2}'.format(fileBasename, 'LPET', fileExtension) else: #-- output long-period equilibrium tide HDF5 file for ASAS/NSIDC granules args = (PRD, YY, MM, DD, HH, MN, SS, TRK, CYCL, GRAN, RL, VERS, AUX) file_format = '{0}_LPET_{1}{2}{3}{4}{5}{6}_{7}{8}{9}_{10}_{11}{12}.h5' OUTPUT_FILE = file_format.format(*args) #-- number of GPS seconds between the GPS epoch #-- and ATLAS Standard Data Product (SDP) epoch atlas_sdp_gps_epoch = IS2_atl06_mds['ancillary_data'][ 'atlas_sdp_gps_epoch'] #-- copy variables for outputting to HDF5 file IS2_atl06_tide = {} IS2_atl06_fill = {} IS2_atl06_dims = {} IS2_atl06_tide_attrs = {} #-- number of GPS seconds between the GPS epoch (1980-01-06T00:00:00Z UTC) #-- and ATLAS Standard Data Product (SDP) epoch (2018-01-01T00:00:00Z UTC) #-- Add this value to delta time parameters to compute full gps_seconds IS2_atl06_tide['ancillary_data'] = {} IS2_atl06_tide_attrs['ancillary_data'] = {} for key in ['atlas_sdp_gps_epoch']: #-- get each HDF5 variable IS2_atl06_tide['ancillary_data'][key] = IS2_atl06_mds[ 'ancillary_data'][key] #-- Getting attributes of group and included variables IS2_atl06_tide_attrs['ancillary_data'][key] = {} for att_name, att_val in IS2_atl06_attrs['ancillary_data'][key].items( ): IS2_atl06_tide_attrs['ancillary_data'][key][att_name] = att_val #-- for each input beam within the file for gtx in sorted(IS2_atl06_beams): #-- output data dictionaries for beam IS2_atl06_tide[gtx] = dict(land_ice_segments={}) IS2_atl06_fill[gtx] = dict(land_ice_segments={}) IS2_atl06_dims[gtx] = dict(land_ice_segments={}) IS2_atl06_tide_attrs[gtx] = dict(land_ice_segments={}) #-- number of segments val = IS2_atl06_mds[gtx]['land_ice_segments'] n_seg = len(val['segment_id']) #-- find valid segments for beam fv = IS2_atl06_attrs[gtx]['land_ice_segments']['h_li']['_FillValue'] #-- convert time from ATLAS SDP to days relative to Jan 1, 1992 gps_seconds = atlas_sdp_gps_epoch + val['delta_time'] leap_seconds = pyTMD.time.count_leap_seconds(gps_seconds) tide_time = pyTMD.time.convert_delta_time(gps_seconds - leap_seconds, epoch1=(1980, 1, 6, 0, 0, 0), epoch2=(1992, 1, 1, 0, 0, 0), scale=1.0 / 86400.0) #-- interpolate delta times from calendar dates to tide time delta_file = get_data_path(['data', 'merged_deltat.data']) deltat = calc_delta_time(delta_file, tide_time) #-- predict long-period equilibrium tides at latitudes and time tide_lpe = np.ma.zeros((n_seg), fill_value=fv) tide_lpe.data[:] = compute_equilibrium_tide(tide_time + deltat, val['latitude']) tide_lpe.mask = (val['latitude'] == fv) | (val['delta_time'] == fv) #-- group attributes for beam IS2_atl06_tide_attrs[gtx]['Description'] = IS2_atl06_attrs[gtx][ 'Description'] IS2_atl06_tide_attrs[gtx]['atlas_pce'] = IS2_atl06_attrs[gtx][ 'atlas_pce'] IS2_atl06_tide_attrs[gtx]['atlas_beam_type'] = IS2_atl06_attrs[gtx][ 'atlas_beam_type'] IS2_atl06_tide_attrs[gtx]['groundtrack_id'] = IS2_atl06_attrs[gtx][ 'groundtrack_id'] IS2_atl06_tide_attrs[gtx]['atmosphere_profile'] = IS2_atl06_attrs[gtx][ 'atmosphere_profile'] IS2_atl06_tide_attrs[gtx]['atlas_spot_number'] = IS2_atl06_attrs[gtx][ 'atlas_spot_number'] IS2_atl06_tide_attrs[gtx]['sc_orientation'] = IS2_atl06_attrs[gtx][ 'sc_orientation'] #-- group attributes for land_ice_segments IS2_atl06_tide_attrs[gtx]['land_ice_segments']['Description'] = ( "The land_ice_segments group " "contains the primary set of derived products. This includes geolocation, height, and " "standard error and quality measures for each segment. This group is sparse, meaning " "that parameters are provided only for pairs of segments for which at least one beam " "has a valid surface-height measurement.") IS2_atl06_tide_attrs[gtx]['land_ice_segments']['data_rate'] = ( "Data within this group are " "sparse. Data values are provided only for those ICESat-2 20m segments where at " "least one beam has a valid land ice height measurement.") #-- geolocation, time and segment ID #-- delta time delta_time = np.ma.array(val['delta_time'], fill_value=fv, mask=(val['delta_time'] == fv)) IS2_atl06_tide[gtx]['land_ice_segments']['delta_time'] = delta_time IS2_atl06_fill[gtx]['land_ice_segments'][ 'delta_time'] = delta_time.fill_value IS2_atl06_dims[gtx]['land_ice_segments']['delta_time'] = None IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time'] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time'][ 'units'] = "seconds since 2018-01-01" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time'][ 'long_name'] = "Elapsed GPS seconds" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time'][ 'standard_name'] = "time" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time'][ 'calendar'] = "standard" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time'][ 'description'] = ( "Number of GPS " "seconds since the ATLAS SDP epoch. The ATLAS Standard Data Products (SDP) epoch offset " "is defined within /ancillary_data/atlas_sdp_gps_epoch as the number of GPS seconds " "between the GPS epoch (1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP epoch. By " "adding the offset contained within atlas_sdp_gps_epoch to delta time parameters, the " "time in gps_seconds relative to the GPS epoch can be computed." ) IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time']['coordinates'] = \ "segment_id latitude longitude" #-- latitude latitude = np.ma.array(val['latitude'], fill_value=fv, mask=(val['latitude'] == fv)) IS2_atl06_tide[gtx]['land_ice_segments']['latitude'] = latitude IS2_atl06_fill[gtx]['land_ice_segments'][ 'latitude'] = latitude.fill_value IS2_atl06_dims[gtx]['land_ice_segments']['latitude'] = ['delta_time'] IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'units'] = "degrees_north" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'contentType'] = "physicalMeasurement" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'long_name'] = "Latitude" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'standard_name'] = "latitude" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'description'] = ("Latitude of " "segment center") IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'valid_min'] = -90.0 IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'valid_max'] = 90.0 IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude']['coordinates'] = \ "segment_id delta_time longitude" #-- longitude longitude = np.ma.array(val['longitude'], fill_value=fv, mask=(val['longitude'] == fv)) IS2_atl06_tide[gtx]['land_ice_segments']['longitude'] = longitude IS2_atl06_fill[gtx]['land_ice_segments'][ 'longitude'] = longitude.fill_value IS2_atl06_dims[gtx]['land_ice_segments']['longitude'] = ['delta_time'] IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'units'] = "degrees_east" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'contentType'] = "physicalMeasurement" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'long_name'] = "Longitude" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'standard_name'] = "longitude" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'description'] = ("Longitude of " "segment center") IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'valid_min'] = -180.0 IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'valid_max'] = 180.0 IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude']['coordinates'] = \ "segment_id delta_time latitude" #-- segment ID IS2_atl06_tide[gtx]['land_ice_segments']['segment_id'] = val[ 'segment_id'] IS2_atl06_fill[gtx]['land_ice_segments']['segment_id'] = None IS2_atl06_dims[gtx]['land_ice_segments']['segment_id'] = ['delta_time'] IS2_atl06_tide_attrs[gtx]['land_ice_segments']['segment_id'] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['segment_id'][ 'units'] = "1" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['segment_id'][ 'contentType'] = "referenceInformation" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['segment_id'][ 'long_name'] = "Along-track segment ID number" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['segment_id'][ 'description'] = ( "A 7 digit number " "identifying the along-track geolocation segment number. These are sequential, starting with " "1 for the first segment after an ascending equatorial crossing node. Equal to the segment_id for " "the second of the two 20m ATL03 segments included in the 40m ATL06 segment" ) IS2_atl06_tide_attrs[gtx]['land_ice_segments']['segment_id']['coordinates'] = \ "delta_time latitude longitude" #-- geophysical variables IS2_atl06_tide[gtx]['land_ice_segments']['geophysical'] = {} IS2_atl06_fill[gtx]['land_ice_segments']['geophysical'] = {} IS2_atl06_dims[gtx]['land_ice_segments']['geophysical'] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ 'Description'] = ( "The geophysical group " "contains parameters used to correct segment heights for geophysical effects, parameters " "related to solar background and parameters indicative of the presence or absence of clouds." ) IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ 'data_rate'] = ( "Data within this group " "are stored at the land_ice_segments segment rate.") #-- computed long-period equilibrium tide IS2_atl06_tide[gtx]['land_ice_segments']['geophysical'][ 'tide_equilibrium'] = tide_lpe IS2_atl06_fill[gtx]['land_ice_segments']['geophysical'][ 'tide_equilibrium'] = tide_lpe.fill_value IS2_atl06_dims[gtx]['land_ice_segments']['geophysical'][ 'tide_equilibrium'] = ['delta_time'] IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ 'tide_equilibrium'] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ 'tide_equilibrium']['units'] = "meters" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ 'tide_equilibrium']['contentType'] = "referenceInformation" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical']['tide_equilibrium']['long_name'] = \ "Long Period Equilibrium Tide" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ 'tide_equilibrium']['description'] = ( "Long-period " "equilibrium tidal elevation from the summation of fifteen tidal spectral lines" ) IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical']['tide_equilibrium']['reference'] = \ "https://doi.org/10.1111/j.1365-246X.1973.tb03420.x" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical']['tide_equilibrium']['coordinates'] = \ "../segment_id ../delta_time ../latitude ../longitude" #-- print file information print('\t{0}'.format(OUTPUT_FILE)) if VERBOSE else None HDF5_ATL06_tide_write(IS2_atl06_tide, IS2_atl06_tide_attrs, CLOBBER=True, INPUT=os.path.basename(INPUT_FILE), FILL_VALUE=IS2_atl06_fill, DIMENSIONS=IS2_atl06_dims, FILENAME=os.path.join(DIRECTORY, OUTPUT_FILE)) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY, OUTPUT_FILE), MODE)
def compute_tidal_elevations(tide_dir, input_file, output_file, TIDE_MODEL=None, ATLAS_FORMAT='netcdf', GZIP=True, DEFINITION_FILE=None, FORMAT='csv', VARIABLES=[], HEADER=0, TYPE='drift', TIME_UNITS='days since 1858-11-17T00:00:00', TIME_STANDARD='UTC', TIME=None, PROJECTION='4326', METHOD='spline', EXTRAPOLATE=False, CUTOFF=None, VERBOSE=False, MODE=0o775): #-- create logger for verbosity level loglevel = logging.INFO if VERBOSE else logging.CRITICAL logging.basicConfig(level=loglevel) #-- get parameters for tide model if DEFINITION_FILE is not None: model = pyTMD.model(tide_dir).from_file(DEFINITION_FILE) else: model = pyTMD.model(tide_dir, format=ATLAS_FORMAT, compressed=GZIP).elevation(TIDE_MODEL) output_variable = model.variable #-- invalid value fill_value = -9999.0 #-- output netCDF4 and HDF5 file attributes #-- will be added to YAML header in csv files attrib = {} #-- latitude attrib['lat'] = {} attrib['lat']['long_name'] = 'Latitude' attrib['lat']['units'] = 'Degrees_North' #-- longitude attrib['lon'] = {} attrib['lon']['long_name'] = 'Longitude' attrib['lon']['units'] = 'Degrees_East' #-- tides attrib[output_variable] = {} attrib[output_variable]['description'] = model.description attrib[output_variable]['reference'] = model.reference attrib[output_variable]['model'] = model.name attrib[output_variable]['units'] = 'meters' attrib[output_variable]['long_name'] = model.long_name attrib[output_variable]['_FillValue'] = fill_value #-- time attrib['time'] = {} attrib['time']['long_name'] = 'Time' attrib['time']['units'] = 'days since 1992-01-01T00:00:00' attrib['time']['calendar'] = 'standard' #-- read input file to extract time, spatial coordinates and data if (FORMAT == 'csv'): dinput = pyTMD.spatial.from_ascii(input_file, columns=VARIABLES, header=HEADER) elif (FORMAT == 'netCDF4'): dinput = pyTMD.spatial.from_netCDF4(input_file, timename=VARIABLES[0], xname=VARIABLES[2], yname=VARIABLES[1], varname=VARIABLES[3]) elif (FORMAT == 'HDF5'): dinput = pyTMD.spatial.from_HDF5(input_file, timename=VARIABLES[0], xname=VARIABLES[2], yname=VARIABLES[1], varname=VARIABLES[3]) elif (FORMAT == 'geotiff'): dinput = pyTMD.spatial.from_geotiff(input_file) #-- copy global geotiff attributes for projection and grid parameters for att_name in ['projection','wkt','spacing','extent']: attrib[att_name] = dinput['attributes'][att_name] #-- update time variable if entered as argument if TIME is not None: dinput['time'] = np.copy(TIME) #-- converting x,y from projection to latitude/longitude crs1 = get_projection(dinput['attributes'], PROJECTION) crs2 = pyproj.CRS.from_string("epsg:{0:d}".format(4326)) transformer = pyproj.Transformer.from_crs(crs1, crs2, always_xy=True) if (TYPE == 'grid'): ny,nx = (len(dinput['y']),len(dinput['x'])) gridx,gridy = np.meshgrid(dinput['x'],dinput['y']) lon,lat = transformer.transform(gridx,gridy) elif (TYPE == 'drift'): lon,lat = transformer.transform(dinput['x'],dinput['y']) #-- extract time units from netCDF4 and HDF5 attributes or from TIME_UNITS try: time_string = dinput['attributes']['time']['units'] epoch1,to_secs = pyTMD.time.parse_date_string(time_string) except (TypeError, KeyError, ValueError): epoch1,to_secs = pyTMD.time.parse_date_string(TIME_UNITS) #-- convert time to seconds delta_time = to_secs*dinput['time'].flatten() #-- calculate leap seconds if specified if (TIME_STANDARD.upper() == 'GPS'): GPS_Epoch_Time = pyTMD.time.convert_delta_time(0, epoch1=epoch1, epoch2=(1980,1,6,0,0,0), scale=1.0) GPS_Time = pyTMD.time.convert_delta_time(delta_time, epoch1=epoch1, epoch2=(1980,1,6,0,0,0), scale=1.0) #-- calculate difference in leap seconds from start of epoch leap_seconds = pyTMD.time.count_leap_seconds(GPS_Time) - \ pyTMD.time.count_leap_seconds(np.atleast_1d(GPS_Epoch_Time)) elif (TIME_STANDARD.upper() == 'LORAN'): #-- LORAN time is ahead of GPS time by 9 seconds GPS_Epoch_Time = pyTMD.time.convert_delta_time(-9.0, epoch1=epoch1, epoch2=(1980,1,6,0,0,0), scale=1.0) GPS_Time = pyTMD.time.convert_delta_time(delta_time-9.0, epoch1=epoch1, epoch2=(1980,1,6,0,0,0), scale=1.0) #-- calculate difference in leap seconds from start of epoch leap_seconds = pyTMD.time.count_leap_seconds(GPS_Time) - \ pyTMD.time.count_leap_seconds(np.atleast_1d(GPS_Epoch_Time)) elif (TIME_STANDARD.upper() == 'TAI'): #-- TAI time is ahead of GPS time by 19 seconds GPS_Epoch_Time = pyTMD.time.convert_delta_time(-19.0, epoch1=epoch1, epoch2=(1980,1,6,0,0,0), scale=1.0) GPS_Time = pyTMD.time.convert_delta_time(delta_time-19.0, epoch1=epoch1, epoch2=(1980,1,6,0,0,0), scale=1.0) #-- calculate difference in leap seconds from start of epoch leap_seconds = pyTMD.time.count_leap_seconds(GPS_Time) - \ pyTMD.time.count_leap_seconds(np.atleast_1d(GPS_Epoch_Time)) else: leap_seconds = 0.0 #-- convert time from units to days since 1992-01-01T00:00:00 tide_time = pyTMD.time.convert_delta_time(delta_time-leap_seconds, epoch1=epoch1, epoch2=(1992,1,1,0,0,0), scale=1.0/86400.0) #-- number of time points nt = len(tide_time) #-- delta time (TT - UT1) file delta_file = pyTMD.utilities.get_data_path(['data','merged_deltat.data']) #-- read tidal constants and interpolate to grid points if model.format in ('OTIS','ATLAS'): amp,ph,D,c = extract_tidal_constants(lon.flatten(), lat.flatten(), model.grid_file, model.model_file, model.projection, TYPE=model.type, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, GRID=model.format) deltat = np.zeros((nt)) elif (model.format == 'netcdf'): amp,ph,D,c = extract_netcdf_constants(lon.flatten(), lat.flatten(), model.grid_file, model.model_file, TYPE=model.type, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) deltat = np.zeros((nt)) elif (model.format == 'GOT'): amp,ph,c = extract_GOT_constants(lon.flatten(), lat.flatten(), model.model_file, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file,tide_time) elif (model.format == 'FES'): amp,ph = extract_FES_constants(lon.flatten(), lat.flatten(), model.model_file, TYPE=model.type, VERSION=model.version, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) #-- available model constituents c = model.constituents #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file,tide_time) #-- calculate complex phase in radians for Euler's cph = -1j*ph*np.pi/180.0 #-- calculate constituent oscillation hc = amp*np.exp(cph) #-- predict tidal elevations at time and infer minor corrections if (TYPE == 'grid'): tide = np.ma.zeros((ny,nx,nt),fill_value=fill_value) tide.mask = np.zeros((ny,nx,nt),dtype=bool) for i in range(nt): TIDE = predict_tide(tide_time[i], hc, c, DELTAT=deltat[i], CORRECTIONS=model.format) MINOR = infer_minor_corrections(tide_time[i], hc, c, DELTAT=deltat[i], CORRECTIONS=model.format) #-- add major and minor components and reform grid tide[:,:,i] = np.reshape((TIDE+MINOR), (ny,nx)) tide.mask[:,:,i] = np.reshape((TIDE.mask | MINOR.mask), (ny,nx)) elif (TYPE == 'drift'): tide = np.ma.zeros((nt), fill_value=fill_value) tide.mask = np.any(hc.mask,axis=1) tide.data[:] = predict_tide_drift(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model.format) minor = infer_minor_corrections(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model.format) tide.data[:] += minor.data[:] #-- replace invalid values with fill value tide.data[tide.mask] = tide.fill_value #-- output to file output = {'time':tide_time,'lon':lon,'lat':lat,output_variable:tide} if (FORMAT == 'csv'): pyTMD.spatial.to_ascii(output, attrib, output_file, delimiter=',', columns=['time','lat','lon',output_variable]) elif (FORMAT == 'netCDF4'): pyTMD.spatial.to_netCDF4(output, attrib, output_file) elif (FORMAT == 'HDF5'): pyTMD.spatial.to_HDF5(output, attrib, output_file) elif (FORMAT == 'geotiff'): pyTMD.spatial.to_geotiff(output, attrib, output_file, varname=output_variable) #-- change the permissions level to MODE os.chmod(output_file, MODE)
def compute_LPET_ICESat2(FILE, VERBOSE=False, MODE=0o775): #-- read data from FILE print('{0} -->'.format(os.path.basename(FILE))) if VERBOSE else None IS2_atl11_mds, IS2_atl11_attrs, IS2_atl11_pairs = read_HDF5_ATL11( FILE, ATTRIBUTES=True) DIRECTORY = os.path.dirname(FILE) #-- extract parameters from ICESat-2 ATLAS HDF5 file name rx = re.compile(r'(processed_)?(ATL\d{2})_(\d{4})(\d{2})_(\d{2})(\d{2})_' r'(\d{3})_(\d{2})(.*?).h5$') SUB, PRD, TRK, GRAN, SCYC, ECYC, RL, VERS, AUX = rx.findall(FILE).pop() #-- number of GPS seconds between the GPS epoch #-- and ATLAS Standard Data Product (SDP) epoch atlas_sdp_gps_epoch = IS2_atl11_mds['ancillary_data'][ 'atlas_sdp_gps_epoch'] #-- copy variables for outputting to HDF5 file IS2_atl11_tide = {} IS2_atl11_fill = {} IS2_atl11_dims = {} IS2_atl11_tide_attrs = {} #-- number of GPS seconds between the GPS epoch (1980-01-06T00:00:00Z UTC) #-- and ATLAS Standard Data Product (SDP) epoch (2018-01-01T00:00:00Z UTC) #-- Add this value to delta time parameters to compute full gps_seconds IS2_atl11_tide['ancillary_data'] = {} IS2_atl11_tide_attrs['ancillary_data'] = {} for key in ['atlas_sdp_gps_epoch']: #-- get each HDF5 variable IS2_atl11_tide['ancillary_data'][key] = IS2_atl11_mds[ 'ancillary_data'][key] #-- Getting attributes of group and included variables IS2_atl11_tide_attrs['ancillary_data'][key] = {} for att_name, att_val in IS2_atl11_attrs['ancillary_data'][key].items( ): IS2_atl11_tide_attrs['ancillary_data'][key][att_name] = att_val #-- for each input beam pair within the file for ptx in sorted(IS2_atl11_pairs): #-- output data dictionaries for beam IS2_atl11_tide[ptx] = dict(cycle_stats={}) IS2_atl11_fill[ptx] = dict(cycle_stats={}) IS2_atl11_dims[ptx] = dict(cycle_stats={}) IS2_atl11_tide_attrs[ptx] = dict(cycle_stats={}) #-- number of average segments and number of included cycles invalid_time = IS2_atl11_attrs[ptx]['delta_time']['_FillValue'] n_points, n_cycles = IS2_atl11_mds[ptx]['delta_time'].shape #-- latitudinal values lat = IS2_atl11_mds[ptx]['latitude'].copy() #-- find valid average segments for beam pair fv = IS2_atl11_attrs[ptx]['h_corr']['_FillValue'] #-- convert time from ATLAS SDP to days relative to Jan 1, 1992 gps_seconds = atlas_sdp_gps_epoch + IS2_atl11_mds[ptx]['delta_time'] leap_seconds = pyTMD.time.count_leap_seconds(gps_seconds) tide_time = pyTMD.time.convert_delta_time(gps_seconds - leap_seconds, epoch1=(1980, 1, 6, 0, 0, 0), epoch2=(1992, 1, 1, 0, 0, 0), scale=1.0 / 86400.0) #-- interpolate delta times from calendar dates to tide time delta_file = get_data_path(['data', 'merged_deltat.data']) deltat = calc_delta_time(delta_file, tide_time) #-- allocate for each cycle tide_lpe = np.ma.empty((n_points, n_cycles), fill_value=fv) tide_lpe.mask = (IS2_atl11_mds[ptx]['delta_time'] == invalid_time) for cycle in range(n_cycles): #-- find valid time and spatial points for cycle valid, = np.nonzero(~tide_lpe.mask[:, cycle]) #-- predict long-period equilibrium tides at latitudes and time t = tide_time[valid, cycle] + deltat[valid, cycle] tide_lpe.data[valid, cycle] = compute_equilibrium_tide(t, lat[valid]) #-- replace masked and nan values with fill value invalid = np.nonzero(np.isnan(tide_lpe.data) | tide_lpe.mask) tide_lpe.data[invalid] = tide_lpe.fill_value tide_lpe.mask[invalid] = True #-- group attributes for beam IS2_atl11_tide_attrs[ptx]['description'] = ( 'Contains the primary science parameters for this ' 'data set') IS2_atl11_tide_attrs[ptx]['beam_pair'] = IS2_atl11_attrs[ptx][ 'beam_pair'] IS2_atl11_tide_attrs[ptx]['ReferenceGroundTrack'] = IS2_atl11_attrs[ ptx]['ReferenceGroundTrack'] IS2_atl11_tide_attrs[ptx]['first_cycle'] = IS2_atl11_attrs[ptx][ 'first_cycle'] IS2_atl11_tide_attrs[ptx]['last_cycle'] = IS2_atl11_attrs[ptx][ 'last_cycle'] IS2_atl11_tide_attrs[ptx]['equatorial_radius'] = IS2_atl11_attrs[ptx][ 'equatorial_radius'] IS2_atl11_tide_attrs[ptx]['polar_radius'] = IS2_atl11_attrs[ptx][ 'polar_radius'] #-- geolocation, time and reference point #-- cycle_number IS2_atl11_tide[ptx]['cycle_number'] = IS2_atl11_mds[ptx][ 'cycle_number'].copy() IS2_atl11_fill[ptx]['cycle_number'] = None IS2_atl11_dims[ptx]['cycle_number'] = None IS2_atl11_tide_attrs[ptx]['cycle_number'] = {} IS2_atl11_tide_attrs[ptx]['cycle_number']['units'] = "1" IS2_atl11_tide_attrs[ptx]['cycle_number'][ 'long_name'] = "Orbital cycle number" IS2_atl11_tide_attrs[ptx]['cycle_number']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['cycle_number']['description'] = ( "Number of 91-day periods " "that have elapsed since ICESat-2 entered the science orbit. Each of the 1,387 " "reference ground track (RGTs) is targeted in the polar regions once " "every 91 days.") #-- delta time IS2_atl11_tide[ptx]['delta_time'] = IS2_atl11_mds[ptx][ 'delta_time'].copy() IS2_atl11_fill[ptx]['delta_time'] = IS2_atl11_attrs[ptx]['delta_time'][ '_FillValue'] IS2_atl11_dims[ptx]['delta_time'] = ['ref_pt', 'cycle_number'] IS2_atl11_tide_attrs[ptx]['delta_time'] = {} IS2_atl11_tide_attrs[ptx]['delta_time'][ 'units'] = "seconds since 2018-01-01" IS2_atl11_tide_attrs[ptx]['delta_time'][ 'long_name'] = "Elapsed GPS seconds" IS2_atl11_tide_attrs[ptx]['delta_time']['standard_name'] = "time" IS2_atl11_tide_attrs[ptx]['delta_time']['calendar'] = "standard" IS2_atl11_tide_attrs[ptx]['delta_time']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['delta_time']['description'] = ( "Number of GPS " "seconds since the ATLAS SDP epoch. The ATLAS Standard Data Products (SDP) epoch offset " "is defined within /ancillary_data/atlas_sdp_gps_epoch as the number of GPS seconds " "between the GPS epoch (1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP epoch. By " "adding the offset contained within atlas_sdp_gps_epoch to delta time parameters, the " "time in gps_seconds relative to the GPS epoch can be computed.") IS2_atl11_tide_attrs[ptx]['delta_time']['coordinates'] = \ "ref_pt cycle_number latitude longitude" #-- latitude IS2_atl11_tide[ptx]['latitude'] = IS2_atl11_mds[ptx]['latitude'].copy() IS2_atl11_fill[ptx]['latitude'] = IS2_atl11_attrs[ptx]['latitude'][ '_FillValue'] IS2_atl11_dims[ptx]['latitude'] = ['ref_pt'] IS2_atl11_tide_attrs[ptx]['latitude'] = {} IS2_atl11_tide_attrs[ptx]['latitude']['units'] = "degrees_north" IS2_atl11_tide_attrs[ptx]['latitude'][ 'contentType'] = "physicalMeasurement" IS2_atl11_tide_attrs[ptx]['latitude']['long_name'] = "Latitude" IS2_atl11_tide_attrs[ptx]['latitude']['standard_name'] = "latitude" IS2_atl11_tide_attrs[ptx]['latitude']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['latitude']['description'] = ( "Center latitude of " "selected segments") IS2_atl11_tide_attrs[ptx]['latitude']['valid_min'] = -90.0 IS2_atl11_tide_attrs[ptx]['latitude']['valid_max'] = 90.0 IS2_atl11_tide_attrs[ptx]['latitude']['coordinates'] = \ "ref_pt delta_time longitude" #-- longitude IS2_atl11_tide[ptx]['longitude'] = IS2_atl11_mds[ptx][ 'longitude'].copy() IS2_atl11_fill[ptx]['longitude'] = IS2_atl11_attrs[ptx]['longitude'][ '_FillValue'] IS2_atl11_dims[ptx]['longitude'] = ['ref_pt'] IS2_atl11_tide_attrs[ptx]['longitude'] = {} IS2_atl11_tide_attrs[ptx]['longitude']['units'] = "degrees_east" IS2_atl11_tide_attrs[ptx]['longitude'][ 'contentType'] = "physicalMeasurement" IS2_atl11_tide_attrs[ptx]['longitude']['long_name'] = "Longitude" IS2_atl11_tide_attrs[ptx]['longitude']['standard_name'] = "longitude" IS2_atl11_tide_attrs[ptx]['longitude']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['longitude']['description'] = ( "Center longitude of " "selected segments") IS2_atl11_tide_attrs[ptx]['longitude']['valid_min'] = -180.0 IS2_atl11_tide_attrs[ptx]['longitude']['valid_max'] = 180.0 IS2_atl11_tide_attrs[ptx]['longitude']['coordinates'] = \ "ref_pt delta_time latitude" #-- reference point IS2_atl11_tide[ptx]['ref_pt'] = IS2_atl11_mds[ptx]['ref_pt'].copy() IS2_atl11_fill[ptx]['ref_pt'] = None IS2_atl11_dims[ptx]['ref_pt'] = None IS2_atl11_tide_attrs[ptx]['ref_pt'] = {} IS2_atl11_tide_attrs[ptx]['ref_pt']['units'] = "1" IS2_atl11_tide_attrs[ptx]['ref_pt'][ 'contentType'] = "referenceInformation" IS2_atl11_tide_attrs[ptx]['ref_pt'][ 'long_name'] = "Reference point number" IS2_atl11_tide_attrs[ptx]['ref_pt']['source'] = "ATL06" IS2_atl11_tide_attrs[ptx]['ref_pt']['description'] = ( "The reference point is the 7 digit segment_id " "number corresponding to the center of the ATL06 data used for each ATL11 point. These are " "sequential, starting with 1 for the first segment after an ascending equatorial crossing node." ) IS2_atl11_tide_attrs[ptx]['ref_pt']['coordinates'] = \ "delta_time latitude longitude" #-- cycle statistics variables IS2_atl11_tide_attrs[ptx]['cycle_stats']['Description'] = ( "The cycle_stats subgroup " "contains summary information about segments for each reference point, including " "the uncorrected mean heights for reference surfaces, blowing snow and cloud " "indicators, and geolocation and height misfit statistics.") IS2_atl11_tide_attrs[ptx]['cycle_stats']['data_rate'] = ( "Data within this group " "are stored at the average segment rate.") #-- computed long-period equilibrium tide IS2_atl11_tide[ptx]['cycle_stats']['tide_equilibrium'] = tide_lpe IS2_atl11_fill[ptx]['cycle_stats'][ 'tide_equilibrium'] = tide_lpe.fill_value IS2_atl11_dims[ptx]['cycle_stats']['tide_equilibrium'] = [ 'ref_pt', 'cycle_number' ] IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium'] = {} IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium'][ 'units'] = "meters" IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium'][ 'contentType'] = "referenceInformation" IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium']['long_name'] = \ "Long Period Equilibrium Tide" IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium'][ 'description'] = ( "Long-period " "equilibrium tidal elevation from the summation of fifteen tidal spectral lines" ) IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium']['reference'] = \ "https://doi.org/10.1111/j.1365-246X.1973.tb03420.x" IS2_atl11_tide_attrs[ptx]['cycle_stats']['tide_equilibrium']['coordinates'] = \ "../ref_pt ../cycle_number ../delta_time ../latitude ../longitude" #-- output tidal HDF5 file args = (PRD, TRK, GRAN, SCYC, ECYC, RL, VERS, AUX) file_format = '{0}_LPET_{1}{2}_{3}{4}_{5}_{6}{7}.h5' #-- print file information print('\t{0}'.format(file_format.format(*args))) if VERBOSE else None HDF5_ATL11_tide_write(IS2_atl11_tide, IS2_atl11_tide_attrs, CLOBBER=True, INPUT=os.path.basename(FILE), FILL_VALUE=IS2_atl11_fill, DIMENSIONS=IS2_atl11_dims, FILENAME=os.path.join(DIRECTORY, file_format.format(*args))) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY, file_format.format(*args)), MODE)
def compute_tide_corrections(x, y, delta_time, DIRECTORY=None, MODEL=None, EPSG=3031, EPOCH=(2000,1,1,0,0,0), TYPE='drift', TIME='UTC', METHOD='spline', EXTRAPOLATE=False, FILL_VALUE=np.nan): """ Compute tides at points and times using tidal harmonics Arguments --------- x: x-coordinates in projection EPSG y: y-coordinates in projection EPSG delta_time: seconds since EPOCH Keyword arguments ----------------- DIRECTORY: working data directory for tide models MODEL: Tide model to use in correction EPOCH: time period for calculating delta times default: J2000 (seconds since 2000-01-01T00:00:00) TYPE: input data type drift: drift buoys or satellite/airborne altimetry (time per data point) grid: spatial grids or images (single time per image) TIME: time type if need to compute leap seconds to convert to UTC GPS: leap seconds needed TAI: leap seconds needed (TAI = GPS + 19 seconds) UTC: no leap seconds needed EPSG: input coordinate system default: 3031 Polar Stereographic South, WGS84 METHOD: interpolation method bilinear: quick bilinear interpolation spline: scipy bivariate spline interpolation linear, nearest: scipy regular grid interpolations FILL_VALUE: output invalid value (default NaN) Returns ------- tide: tidal elevation at coordinates and time in meters """ #-- select between tide models if (MODEL == 'CATS0201'): grid_file = os.path.join(DIRECTORY,'cats0201_tmd','grid_CATS') model_file = os.path.join(DIRECTORY,'cats0201_tmd','h0_CATS02_01') model_format = 'OTIS' model_EPSG = '4326' model_type = 'z' elif (MODEL == 'CATS2008'): grid_file = os.path.join(DIRECTORY,'CATS2008','grid_CATS2008') model_file = os.path.join(DIRECTORY,'CATS2008','hf.CATS2008.out') model_format = 'OTIS' model_EPSG = 'CATS2008' model_type = 'z' elif (MODEL == 'CATS2008_load'): grid_file = os.path.join(DIRECTORY,'CATS2008a_SPOTL_Load','grid_CATS2008a_opt') model_file = os.path.join(DIRECTORY,'CATS2008a_SPOTL_Load','h_CATS2008a_SPOTL_load') model_format = 'OTIS' model_EPSG = 'CATS2008' model_type = 'z' elif (MODEL == 'TPXO9-atlas'): model_directory = os.path.join(DIRECTORY,'TPXO9_atlas') grid_file = os.path.join(model_directory,'grid_tpxo9_atlas.nc.gz') model_files = ['h_q1_tpxo9_atlas_30.nc.gz','h_o1_tpxo9_atlas_30.nc.gz', 'h_p1_tpxo9_atlas_30.nc.gz','h_k1_tpxo9_atlas_30.nc.gz', 'h_n2_tpxo9_atlas_30.nc.gz','h_m2_tpxo9_atlas_30.nc.gz', 'h_s2_tpxo9_atlas_30.nc.gz','h_k2_tpxo9_atlas_30.nc.gz', 'h_m4_tpxo9_atlas_30.nc.gz','h_ms4_tpxo9_atlas_30.nc.gz', 'h_mn4_tpxo9_atlas_30.nc.gz','h_2n2_tpxo9_atlas_30.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] model_format = 'netcdf' model_type = 'z' SCALE = 1.0/1000.0 GZIP = True elif (MODEL == 'TPXO9-atlas-v2'): model_directory = os.path.join(DIRECTORY,'TPXO9_atlas_v2') grid_file = os.path.join(model_directory,'grid_tpxo9_atlas_30_v2.nc.gz') model_files = ['h_q1_tpxo9_atlas_30_v2.nc.gz','h_o1_tpxo9_atlas_30_v2.nc.gz', 'h_p1_tpxo9_atlas_30_v2.nc.gz','h_k1_tpxo9_atlas_30_v2.nc.gz', 'h_n2_tpxo9_atlas_30_v2.nc.gz','h_m2_tpxo9_atlas_30_v2.nc.gz', 'h_s2_tpxo9_atlas_30_v2.nc.gz','h_k2_tpxo9_atlas_30_v2.nc.gz', 'h_m4_tpxo9_atlas_30_v2.nc.gz','h_ms4_tpxo9_atlas_30_v2.nc.gz', 'h_mn4_tpxo9_atlas_30_v2.nc.gz','h_2n2_tpxo9_atlas_30_v2.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] model_format = 'netcdf' model_type = 'z' SCALE = 1.0/1000.0 GZIP = True elif (MODEL == 'TPXO9-atlas-v3'): model_directory = os.path.join(DIRECTORY,'TPXO9_atlas_v3') grid_file = os.path.join(model_directory,'grid_tpxo9_atlas_30_v3.nc.gz') model_files = ['h_q1_tpxo9_atlas_30_v3.nc.gz','h_o1_tpxo9_atlas_30_v3.nc.gz', 'h_p1_tpxo9_atlas_30_v3.nc.gz','h_k1_tpxo9_atlas_30_v3.nc.gz', 'h_n2_tpxo9_atlas_30_v3.nc.gz','h_m2_tpxo9_atlas_30_v3.nc.gz', 'h_s2_tpxo9_atlas_30_v3.nc.gz','h_k2_tpxo9_atlas_30_v3.nc.gz', 'h_m4_tpxo9_atlas_30_v3.nc.gz','h_ms4_tpxo9_atlas_30_v3.nc.gz', 'h_mn4_tpxo9_atlas_30_v3.nc.gz','h_2n2_tpxo9_atlas_30_v3.nc.gz', 'h_mf_tpxo9_atlas_30_v3.nc.gz','h_mm_tpxo9_atlas_30_v3.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] model_format = 'netcdf' model_type = 'z' SCALE = 1.0/1000.0 GZIP = True elif (MODEL == 'TPXO9-atlas-v4'): model_directory = os.path.join(DIRECTORY,'TPXO9_atlas_v4') grid_file = os.path.join(model_directory,'grid_tpxo9_atlas_30_v4') model_files = ['h_q1_tpxo9_atlas_30_v4','h_o1_tpxo9_atlas_30_v4', 'h_p1_tpxo9_atlas_30_v4','h_k1_tpxo9_atlas_30_v4', 'h_n2_tpxo9_atlas_30_v4','h_m2_tpxo9_atlas_30_v4', 'h_s2_tpxo9_atlas_30_v4','h_k2_tpxo9_atlas_30_v4', 'h_m4_tpxo9_atlas_30_v4','h_ms4_tpxo9_atlas_30_v4', 'h_mn4_tpxo9_atlas_30_v4','h_2n2_tpxo9_atlas_30_v4', 'h_mf_tpxo9_atlas_30_v4','h_mm_tpxo9_atlas_30_v4'] model_file = [os.path.join(model_directory,m) for m in model_files] model_format = 'OTIS' model_EPSG = '4326' model_type = 'z' elif (MODEL == 'TPXO9.1'): grid_file = os.path.join(DIRECTORY,'TPXO9.1','DATA','grid_tpxo9') model_file = os.path.join(DIRECTORY,'TPXO9.1','DATA','h_tpxo9.v1') model_format = 'OTIS' model_EPSG = '4326' model_type = 'z' elif (MODEL == 'TPXO8-atlas'): grid_file = os.path.join(DIRECTORY,'tpxo8_atlas','grid_tpxo8atlas_30_v1') model_file = os.path.join(DIRECTORY,'tpxo8_atlas','hf.tpxo8_atlas_30_v1') model_format = 'ATLAS' model_EPSG = '4326' model_type = 'z' elif (MODEL == 'TPXO7.2'): grid_file = os.path.join(DIRECTORY,'TPXO7.2_tmd','grid_tpxo7.2') model_file = os.path.join(DIRECTORY,'TPXO7.2_tmd','h_tpxo7.2') model_format = 'OTIS' model_EPSG = '4326' model_type = 'z' elif (MODEL == 'TPXO7.2_load'): grid_file = os.path.join(DIRECTORY,'TPXO7.2_load','grid_tpxo6.2') model_file = os.path.join(DIRECTORY,'TPXO7.2_load','h_tpxo7.2_load') model_format = 'OTIS' model_EPSG = '4326' model_type = 'z' elif (MODEL == 'AODTM-5'): grid_file = os.path.join(DIRECTORY,'aodtm5_tmd','grid_Arc5km') model_file = os.path.join(DIRECTORY,'aodtm5_tmd','h0_Arc5km.oce') model_format = 'OTIS' model_EPSG = 'PSNorth' model_type = 'z' elif (MODEL == 'AOTIM-5'): grid_file = os.path.join(DIRECTORY,'aotim5_tmd','grid_Arc5km') model_file = os.path.join(DIRECTORY,'aotim5_tmd','h_Arc5km.oce') model_format = 'OTIS' model_EPSG = 'PSNorth' model_type = 'z' elif (MODEL == 'AOTIM-5-2018'): grid_file = os.path.join(DIRECTORY,'Arc5km2018','grid_Arc5km2018') model_file = os.path.join(DIRECTORY,'Arc5km2018','h_Arc5km2018') model_format = 'OTIS' model_EPSG = 'PSNorth' model_type = 'z' elif (MODEL == 'GOT4.7'): model_directory = os.path.join(DIRECTORY,'GOT4.7','grids_oceantide') model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz', 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] model_format = 'GOT' SCALE = 1.0/100.0 GZIP = True elif (MODEL == 'GOT4.7_load'): model_directory = os.path.join(DIRECTORY,'GOT4.7','grids_loadtide') model_files = ['q1load.d.gz','o1load.d.gz','p1load.d.gz','k1load.d.gz', 'n2load.d.gz','m2load.d.gz','s2load.d.gz','k2load.d.gz', 's1load.d.gz','m4load.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] model_format = 'GOT' SCALE = 1.0/1000.0 GZIP = True elif (MODEL == 'GOT4.8'): model_directory = os.path.join(DIRECTORY,'got4.8','grids_oceantide') model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz', 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] model_format = 'GOT' SCALE = 1.0/100.0 GZIP = True elif (MODEL == 'GOT4.8_load'): model_directory = os.path.join(DIRECTORY,'got4.8','grids_loadtide') model_files = ['q1load.d.gz','o1load.d.gz','p1load.d.gz','k1load.d.gz', 'n2load.d.gz','m2load.d.gz','s2load.d.gz','k2load.d.gz', 's1load.d.gz','m4load.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] model_format = 'GOT' SCALE = 1.0/1000.0 GZIP = True elif (MODEL == 'GOT4.10'): model_directory = os.path.join(DIRECTORY,'GOT4.10c','grids_oceantide') model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz', 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] model_format = 'GOT' SCALE = 1.0/100.0 GZIP = True elif (MODEL == 'GOT4.10_load'): model_directory = os.path.join(DIRECTORY,'GOT4.10c','grids_loadtide') model_files = ['q1load.d.gz','o1load.d.gz','p1load.d.gz','k1load.d.gz', 'n2load.d.gz','m2load.d.gz','s2load.d.gz','k2load.d.gz', 's1load.d.gz','m4load.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] model_format = 'GOT' SCALE = 1.0/1000.0 GZIP = True elif (MODEL == 'FES2014'): model_directory = os.path.join(DIRECTORY,'fes2014','ocean_tide') model_files = ['2n2.nc.gz','eps2.nc.gz','j1.nc.gz','k1.nc.gz', 'k2.nc.gz','l2.nc.gz','la2.nc.gz','m2.nc.gz','m3.nc.gz','m4.nc.gz', 'm6.nc.gz','m8.nc.gz','mf.nc.gz','mks2.nc.gz','mm.nc.gz', 'mn4.nc.gz','ms4.nc.gz','msf.nc.gz','msqm.nc.gz','mtm.nc.gz', 'mu2.nc.gz','n2.nc.gz','n4.nc.gz','nu2.nc.gz','o1.nc.gz','p1.nc.gz', 'q1.nc.gz','r2.nc.gz','s1.nc.gz','s2.nc.gz','s4.nc.gz','sa.nc.gz', 'ssa.nc.gz','t2.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] c = ['2n2','eps2','j1','k1','k2','l2','lambda2','m2','m3','m4','m6','m8', 'mf','mks2','mm','mn4','ms4','msf','msqm','mtm','mu2','n2','n4', 'nu2','o1','p1','q1','r2','s1','s2','s4','sa','ssa','t2'] model_format = 'FES' TYPE = 'z' SCALE = 1.0/100.0 GZIP = True elif (MODEL == 'FES2014_load'): model_directory = os.path.join(DIRECTORY,'fes2014','load_tide') model_files = ['2n2.nc.gz','eps2.nc.gz','j1.nc.gz','k1.nc.gz', 'k2.nc.gz','l2.nc.gz','la2.nc.gz','m2.nc.gz','m3.nc.gz','m4.nc.gz', 'm6.nc.gz','m8.nc.gz','mf.nc.gz','mks2.nc.gz','mm.nc.gz', 'mn4.nc.gz','ms4.nc.gz','msf.nc.gz','msqm.nc.gz','mtm.nc.gz', 'mu2.nc.gz','n2.nc.gz','n4.nc.gz','nu2.nc.gz','o1.nc.gz','p1.nc.gz', 'q1.nc.gz','r2.nc.gz','s1.nc.gz','s2.nc.gz','s4.nc.gz','sa.nc.gz', 'ssa.nc.gz','t2.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] c = ['2n2','eps2','j1','k1','k2','l2','lambda2','m2','m3','m4','m6', 'm8','mf','mks2','mm','mn4','ms4','msf','msqm','mtm','mu2','n2', 'n4','nu2','o1','p1','q1','r2','s1','s2','s4','sa','ssa','t2'] model_format = 'FES' model_type = 'z' SCALE = 1.0/100.0 GZIP = True else: raise Exception("Unlisted tide model") #-- converting x,y from EPSG to latitude/longitude crs1 = pyproj.CRS.from_string("epsg:{0:d}".format(EPSG)) crs2 = pyproj.CRS.from_string("epsg:{0:d}".format(4326)) transformer = pyproj.Transformer.from_crs(crs1, crs2, always_xy=True) lon,lat = transformer.transform(x.flatten(), y.flatten()) #-- assert delta time is an array delta_time = np.atleast_1d(delta_time) #-- calculate leap seconds if specified if (TIME.upper() == 'GPS'): GPS_Epoch_Time = pyTMD.time.convert_delta_time(0, epoch1=EPOCH, epoch2=(1980,1,6,0,0,0), scale=1.0) GPS_Time = pyTMD.time.convert_delta_time(delta_time, epoch1=EPOCH, epoch2=(1980,1,6,0,0,0), scale=1.0) #-- calculate difference in leap seconds from start of epoch leap_seconds = pyTMD.time.count_leap_seconds(GPS_Time) - \ pyTMD.time.count_leap_seconds(np.atleast_1d(GPS_Epoch_Time)) elif (TIME.upper() == 'TAI'): #-- TAI time is ahead of GPS time by 19 seconds GPS_Epoch_Time = pyTMD.time.convert_delta_time(-19.0, epoch1=EPOCH, epoch2=(1980,1,6,0,0,0), scale=1.0) GPS_Time = pyTMD.time.convert_delta_time(delta_time-19.0, epoch1=EPOCH, epoch2=(1980,1,6,0,0,0), scale=1.0) #-- calculate difference in leap seconds from start of epoch leap_seconds = pyTMD.time.count_leap_seconds(GPS_Time) - \ pyTMD.time.count_leap_seconds(np.atleast_1d(GPS_Epoch_Time)) else: leap_seconds = 0.0 #-- convert time to days relative to Jan 1, 1992 (48622mjd) t = pyTMD.time.convert_delta_time(delta_time - leap_seconds, epoch1=EPOCH, epoch2=(1992,1,1,0,0,0), scale=(1.0/86400.0)) #-- delta time (TT - UT1) file delta_file = pyTMD.utilities.get_data_path(['data','merged_deltat.data']) #-- read tidal constants and interpolate to grid points if model_format in ('OTIS','ATLAS'): amp,ph,D,c = extract_tidal_constants(lon, lat, grid_file, model_file, model_EPSG, TYPE=model_type, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, GRID=model_format) deltat = np.zeros_like(t) elif (model_format == 'netcdf'): amp,ph,D,c = extract_netcdf_constants(lon, lat, grid_file, model_file, TYPE=model_type, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=SCALE, GZIP=GZIP) deltat = np.zeros_like(t) elif (model_format == 'GOT'): amp,ph,c = extract_GOT_constants(lon, lat, model_file, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=SCALE, GZIP=GZIP) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, t) elif (model_format == 'FES'): amp,ph = extract_FES_constants(lon, lat, model_file, TYPE=model_type, VERSION=MODEL, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=SCALE, GZIP=GZIP) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, t) #-- calculate complex phase in radians for Euler's cph = -1j*ph*np.pi/180.0 #-- calculate constituent oscillation hc = amp*np.exp(cph) #-- predict tidal elevations at time and infer minor corrections if (TYPE.lower() == 'grid'): ny,nx = np.shape(x); nt = len(t) tide = np.ma.zeros((ny,nx,nt),fill_value=FILL_VALUE) tide.mask = np.zeros((ny,nx,nt),dtype=bool) for i in range(nt): TIDE = predict_tide(t[i], hc, c, DELTAT=deltat[i], CORRECTIONS=model_format) MINOR = infer_minor_corrections(t[i], hc, c, DELTAT=deltat[i], CORRECTIONS=model_format) #-- add major and minor components and reform grid tide[:,:,i] = np.reshape((TIDE+MINOR), (ny,nx)) tide.mask[:,:,i] = np.reshape((TIDE.mask | MINOR.mask), (ny,nx)) else: npts = len(t) tide = np.ma.zeros((npts), fill_value=FILL_VALUE) tide.mask = np.any(hc.mask,axis=1) tide.data[:] = predict_tide_drift(t, hc, c, DELTAT=deltat, CORRECTIONS=model_format) minor = infer_minor_corrections(t, hc, c, DELTAT=deltat, CORRECTIONS=model_format) tide.data[:] += minor.data[:] #-- replace invalid values with fill value tide.data[tide.mask] = tide.fill_value #-- return the tide correction return tide
def compute_tides_ICESat2(tide_dir, FILE, MODEL, VERBOSE=False, MODE=0o775): #-- select between tide models if (MODEL == 'CATS0201'): grid_file = os.path.join(tide_dir, 'cats0201_tmd', 'grid_CATS') model_file = os.path.join(tide_dir, 'cats0201_tmd', 'h0_CATS02_01') reference = 'https://mail.esr.org/polar_tide_models/Model_CATS0201.html' variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' type = 'z' elif (MODEL == 'CATS2008'): grid_file = os.path.join(tide_dir, 'CATS2008', 'grid_CATS2008a_opt') model_file = os.path.join(tide_dir, 'CATS2008', 'hf.CATS2008.out') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = 'CATS2008' type = 'z' elif (MODEL == 'CATS2008_load'): grid_file = os.path.join(tide_dir, 'CATS2008a_SPOTL_Load', 'grid_CATS2008a_opt') model_file = os.path.join(tide_dir, 'CATS2008a_SPOTL_Load', 'h_CATS2008a_SPOTL_load') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') variable = 'tide_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'OTIS' EPSG = 'CATS2008' type = 'z' elif (MODEL == 'TPXO9-atlas'): model_directory = os.path.join(tide_dir, 'TPXO9_atlas') grid_file = 'grid_tpxo9_atlas.nc.gz' model_files = [ 'h_q1_tpxo9_atlas_30.nc.gz', 'h_o1_tpxo9_atlas_30.nc.gz', 'h_p1_tpxo9_atlas_30.nc.gz', 'h_k1_tpxo9_atlas_30.nc.gz', 'h_n2_tpxo9_atlas_30.nc.gz', 'h_m2_tpxo9_atlas_30.nc.gz', 'h_s2_tpxo9_atlas_30.nc.gz', 'h_k2_tpxo9_atlas_30.nc.gz', 'h_m4_tpxo9_atlas_30.nc.gz', 'h_ms4_tpxo9_atlas_30.nc.gz', 'h_mn4_tpxo9_atlas_30.nc.gz', 'h_2n2_tpxo9_atlas_30.nc.gz' ] reference = 'http://volkov.oce.orst.edu/tides/tpxo9_atlas.html' variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'netcdf' type = 'z' SCALE = 1.0 / 1000.0 elif (MODEL == 'TPXO9.1'): grid_file = os.path.join(tide_dir, 'TPXO9.1', 'DATA', 'grid_tpxo9') model_file = os.path.join(tide_dir, 'TPXO9.1', 'DATA', 'h_tpxo9.v1') reference = 'http://volkov.oce.orst.edu/tides/global.html' variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' type = 'z' elif (MODEL == 'TPXO8-atlas'): grid_file = os.path.join(tide_dir, 'tpxo8_atlas', 'grid_tpxo8atlas_30_v1') model_file = os.path.join(tide_dir, 'tpxo8_atlas', 'hf.tpxo8_atlas_30_v1') reference = 'http://volkov.oce.orst.edu/tides/tpxo8_atlas.html' variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'ATLAS' EPSG = '4326' type = 'z' elif (MODEL == 'TPXO7.2'): grid_file = os.path.join(tide_dir, 'TPXO7.2_tmd', 'grid_tpxo7.2') model_file = os.path.join(tide_dir, 'TPXO7.2_tmd', 'h_tpxo7.2') reference = 'http://volkov.oce.orst.edu/tides/global.html' variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' type = 'z' elif (MODEL == 'TPXO7.2_load'): grid_file = os.path.join(tide_dir, 'TPXO7.2_load', 'grid_tpxo6.2') model_file = os.path.join(tide_dir, 'TPXO7.2_load', 'h_tpxo7.2_load') reference = 'http://volkov.oce.orst.edu/tides/global.html' variable = 'tide_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'OTIS' EPSG = '4326' type = 'z' elif (MODEL == 'AODTM-5'): grid_file = os.path.join(tide_dir, 'aodtm5_tmd', 'grid_Arc5km') model_file = os.path.join(tide_dir, 'aodtm5_tmd', 'h0_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aodtm-5/') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '3996' type = 'z' elif (MODEL == 'AOTIM-5'): grid_file = os.path.join(tide_dir, 'aotim5_tmd', 'grid_Arc5km') model_file = os.path.join(tide_dir, 'aotim5_tmd', 'h_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '3996' type = 'z' elif (MODEL == 'GOT4.7'): model_directory = os.path.join(tide_dir, 'GOT4.7', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'GOT' SCALE = 1.0 / 100.0 elif (MODEL == 'GOT4.7_load'): model_directory = os.path.join(tide_dir, 'GOT4.7', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'tide_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'GOT' SCALE = 1.0 / 1000.0 elif (MODEL == 'GOT4.8'): model_directory = os.path.join(tide_dir, 'got4.8', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'GOT' SCALE = 1.0 / 100.0 elif (MODEL == 'GOT4.8_load'): model_directory = os.path.join(tide_dir, 'got4.8', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'tide_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'GOT' SCALE = 1.0 / 1000.0 elif (MODEL == 'GOT4.10'): model_directory = os.path.join(tide_dir, 'GOT4.10c', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'tide_ocean' long_name = "Ocean Tide" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'GOT' SCALE = 1.0 / 100.0 elif (MODEL == 'GOT4.10_load'): model_directory = os.path.join(tide_dir, 'GOT4.10c', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'tide_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'GOT' SCALE = 1.0 / 1000.0 #-- read data from FILE print('{0} -->'.format(os.path.basename(FILE))) if VERBOSE else None IS2_atl06_mds, IS2_atl06_attrs, IS2_atl06_beams = read_HDF5_ATL06( FILE, ATTRIBUTES=True) DIRECTORY = os.path.dirname(FILE) #-- extract parameters from ICESat-2 ATLAS HDF5 file name rx = re.compile( '(processed_)?(ATL\d{2})_(\d{4})(\d{2})(\d{2})(\d{2})' '(\d{2})(\d{2})_(\d{4})(\d{2})(\d{2})_(\d{3})_(\d{2})(.*?).h5$') SUB, PRD, YY, MM, DD, HH, MN, SS, TRK, CYCL, GRAN, RL, VERS, AUX = rx.findall( FILE).pop() #-- number of GPS seconds between the GPS epoch #-- and ATLAS Standard Data Product (SDP) epoch atlas_sdp_gps_epoch = IS2_atl06_mds['ancillary_data'][ 'atlas_sdp_gps_epoch'] #-- copy variables for outputting to HDF5 file IS2_atl06_tide = {} IS2_atl06_fill = {} IS2_atl06_tide_attrs = {} #-- number of GPS seconds between the GPS epoch (1980-01-06T00:00:00Z UTC) #-- and ATLAS Standard Data Product (SDP) epoch (2018-01-01T00:00:00Z UTC) #-- Add this value to delta time parameters to compute full gps_seconds IS2_atl06_tide['ancillary_data'] = {} IS2_atl06_tide_attrs['ancillary_data'] = {} for key in ['atlas_sdp_gps_epoch']: #-- get each HDF5 variable IS2_atl06_tide['ancillary_data'][key] = IS2_atl06_mds[ 'ancillary_data'][key] #-- Getting attributes of group and included variables IS2_atl06_tide_attrs['ancillary_data'][key] = {} for att_name, att_val in IS2_atl06_attrs['ancillary_data'][key].items( ): IS2_atl06_tide_attrs['ancillary_data'][key][att_name] = att_val #-- for each input beam within the file for gtx in sorted(IS2_atl06_beams): #-- output data dictionaries for beam IS2_atl06_tide[gtx] = dict(land_ice_segments={}) IS2_atl06_fill[gtx] = dict(land_ice_segments={}) IS2_atl06_tide_attrs[gtx] = dict(land_ice_segments={}) #-- number of segments val = IS2_atl06_mds[gtx]['land_ice_segments'] n_seg = len(val['segment_id']) #-- find valid segments for beam fv = IS2_atl06_attrs[gtx]['land_ice_segments']['h_li']['_FillValue'] h_li = np.ma.array(val['h_li'], fill_value=fv, mask=(val['h_li'] == fv)) ii, = np.nonzero(~h_li.mask) #-- convert time from ATLAS SDP to days relative to Jan 1, 1992 gps_seconds = atlas_sdp_gps_epoch + val['delta_time'][ii] tide_time = (gps_seconds - count_leap_seconds(gps_seconds)) / 86400.0 - 4378.0 #-- read tidal constants and interpolate to grid points if model_format in ('OTIS', 'ATLAS'): amp, ph, D, c = extract_tidal_constants(val['longitude'][ii], val['latitude'][ii], grid_file, model_file, EPSG, type, METHOD='spline', GRID=model_format) deltat = np.zeros_like(tide_time) elif (model_format == 'netcdf'): amp, ph, D, c = extract_netcdf_constants(val['longitude'][ii], val['latitude'][ii], model_directory, grid_file, model_files, type, METHOD='spline', SCALE=SCALE) deltat = np.zeros_like(tide_time) elif (model_format == 'GOT'): amp, ph = extract_GOT_constants(val['longitude'][ii], val['latitude'][ii], model_directory, model_files, METHOD='spline', SCALE=SCALE) #-- convert time to Modified Julian Days for calculating deltat delta_file = os.path.join(tide_dir, 'deltat.data') deltat = calc_delta_time(delta_file, tide_time + 48622.0) cph = -1j * ph * np.pi / 180.0 hc = amp * np.exp(cph) #-- predict tidal elevations at time and infer minor corrections tide = np.ma.empty((n_seg), fill_value=fv) tide.mask = np.copy(h_li.mask) tide.data[ii] = predict_tide_drift(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model_format) tide.data[ii] += infer_minor_corrections(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model_format) #-- replace masked and nan values with fill value invalid, = np.nonzero(np.isnan(tide.data) | tide.mask) tide.data[invalid] = tide.fill_value tide.mask[invalid] = True #-- group attributes for beam IS2_atl06_tide_attrs[gtx]['Description'] = IS2_atl06_attrs[gtx][ 'Description'] IS2_atl06_tide_attrs[gtx]['atlas_pce'] = IS2_atl06_attrs[gtx][ 'atlas_pce'] IS2_atl06_tide_attrs[gtx]['atlas_beam_type'] = IS2_atl06_attrs[gtx][ 'atlas_beam_type'] IS2_atl06_tide_attrs[gtx]['groundtrack_id'] = IS2_atl06_attrs[gtx][ 'groundtrack_id'] IS2_atl06_tide_attrs[gtx]['atmosphere_profile'] = IS2_atl06_attrs[gtx][ 'atmosphere_profile'] IS2_atl06_tide_attrs[gtx]['atlas_spot_number'] = IS2_atl06_attrs[gtx][ 'atlas_spot_number'] IS2_atl06_tide_attrs[gtx]['sc_orientation'] = IS2_atl06_attrs[gtx][ 'sc_orientation'] #-- group attributes for land_ice_segments IS2_atl06_tide_attrs[gtx]['land_ice_segments']['Description'] = ( "The land_ice_segments group " "contains the primary set of derived products. This includes geolocation, height, and " "standard error and quality measures for each segment. This group is sparse, meaning " "that parameters are provided only for pairs of segments for which at least one beam " "has a valid surface-height measurement.") IS2_atl06_tide_attrs[gtx]['land_ice_segments']['data_rate'] = ( "Data within this group are " "sparse. Data values are provided only for those ICESat-2 20m segments where at " "least one beam has a valid land ice height measurement.") #-- geolocation, time and segment ID #-- delta time delta_time = np.ma.array(val['delta_time'], fill_value=fv, mask=(val['delta_time'] == fv)) IS2_atl06_tide[gtx]['land_ice_segments']['delta_time'] = delta_time IS2_atl06_fill[gtx]['land_ice_segments'][ 'delta_time'] = delta_time.fill_value IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time'] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time'][ 'units'] = "seconds since 2018-01-01" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time'][ 'long_name'] = "Elapsed GPS seconds" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time'][ 'standard_name'] = "time" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time'][ 'calendar'] = "standard" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time'][ 'description'] = ( "Number of GPS " "seconds since the ATLAS SDP epoch. The ATLAS Standard Data Products (SDP) epoch offset " "is defined within /ancillary_data/atlas_sdp_gps_epoch as the number of GPS seconds " "between the GPS epoch (1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP epoch. By " "adding the offset contained within atlas_sdp_gps_epoch to delta time parameters, the " "time in gps_seconds relative to the GPS epoch can be computed." ) IS2_atl06_tide_attrs[gtx]['land_ice_segments']['delta_time']['coordinates'] = \ "segment_id latitude longitude" #-- latitude latitude = np.ma.array(val['latitude'], fill_value=fv, mask=(val['latitude'] == fv)) IS2_atl06_tide[gtx]['land_ice_segments']['latitude'] = latitude IS2_atl06_fill[gtx]['land_ice_segments'][ 'latitude'] = latitude.fill_value IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'units'] = "degrees_north" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'contentType'] = "physicalMeasurement" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'long_name'] = "Latitude" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'standard_name'] = "latitude" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'description'] = ("Latitude of " "segment center") IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'valid_min'] = -90.0 IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude'][ 'valid_max'] = 90.0 IS2_atl06_tide_attrs[gtx]['land_ice_segments']['latitude']['coordinates'] = \ "segment_id delta_time longitude" #-- longitude longitude = np.ma.array(val['longitude'], fill_value=fv, mask=(val['longitude'] == fv)) IS2_atl06_tide[gtx]['land_ice_segments']['longitude'] = longitude IS2_atl06_fill[gtx]['land_ice_segments'][ 'longitude'] = longitude.fill_value IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'units'] = "degrees_east" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'contentType'] = "physicalMeasurement" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'long_name'] = "Longitude" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'standard_name'] = "longitude" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'description'] = ("Longitude of " "segment center") IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'valid_min'] = -180.0 IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude'][ 'valid_max'] = 180.0 IS2_atl06_tide_attrs[gtx]['land_ice_segments']['longitude']['coordinates'] = \ "segment_id delta_time latitude" #-- segment ID IS2_atl06_tide[gtx]['land_ice_segments']['segment_id'] = val[ 'segment_id'] IS2_atl06_fill[gtx]['land_ice_segments']['segment_id'] = None IS2_atl06_tide_attrs[gtx]['land_ice_segments']['segment_id'] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['segment_id'][ 'units'] = "1" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['segment_id'][ 'contentType'] = "referenceInformation" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['segment_id'][ 'long_name'] = "Along-track segment ID number" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['segment_id'][ 'description'] = ( "A 7 digit number " "identifying the along-track geolocation segment number. These are sequential, starting with " "1 for the first segment after an ascending equatorial crossing node. Equal to the segment_id for " "the second of the two 20m ATL03 segments included in the 40m ATL06 segment" ) IS2_atl06_tide_attrs[gtx]['land_ice_segments']['segment_id']['coordinates'] = \ "delta_time latitude longitude" #-- geophysical variables IS2_atl06_tide[gtx]['land_ice_segments']['geophysical'] = {} IS2_atl06_fill[gtx]['land_ice_segments']['geophysical'] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ 'Description'] = ( "The geophysical group " "contains parameters used to correct segment heights for geophysical effects, parameters " "related to solar background and parameters indicative of the presence or absence of clouds." ) IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ 'data_rate'] = ( "Data within this group " "are stored at the land_ice_segments segment rate.") #-- computed tide IS2_atl06_tide[gtx]['land_ice_segments']['geophysical'][ variable] = tide IS2_atl06_fill[gtx]['land_ice_segments']['geophysical'][ variable] = tide.fill_value IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ variable] = {} IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ variable]['units'] = "meters" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ variable]['contentType'] = "referenceInformation" IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ variable]['long_name'] = long_name IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ variable]['description'] = description IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ variable]['source'] = MODEL IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][ variable]['reference'] = reference IS2_atl06_tide_attrs[gtx]['land_ice_segments']['geophysical'][variable]['coordinates'] = \ "../segment_id ../delta_time ../latitude ../longitude" #-- output tidal HDF5 file args = (PRD, MODEL, YY, MM, DD, HH, MN, SS, TRK, CYCL, GRAN, RL, VERS, AUX) file_format = '{0}_{1}_TIDES_{2}{3}{4}{5}{6}{7}_{8}{9}{10}_{11}_{12}{13}.h5' #-- print file information print('\t{0}'.format(file_format.format(*args))) if VERBOSE else None HDF5_ATL06_tide_write(IS2_atl06_tide, IS2_atl06_tide_attrs, CLOBBER='Y', INPUT=os.path.basename(FILE), FILL_VALUE=IS2_atl06_fill, FILENAME=os.path.join(DIRECTORY, file_format.format(*args))) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY, file_format.format(*args)), MODE)
def compute_tidal_elevations(tide_dir, input_file, output_file, TIDE_MODEL=None, FORMAT='csv', VARIABLES=['time','lat','lon','data'], TIME_UNITS='days since 1858-11-17T00:00:00', PROJECTION='4326', METHOD='spline', VERBOSE=False, MODE=0o775): #-- select between tide models if (TIDE_MODEL == 'CATS0201'): grid_file = os.path.join(tide_dir,'cats0201_tmd','grid_CATS') model_file = os.path.join(tide_dir,'cats0201_tmd','h0_CATS02_01') reference = 'https://mail.esr.org/polar_tide_models/Model_CATS0201.html' output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'CATS2008'): grid_file = os.path.join(tide_dir,'CATS2008','grid_CATS2008') model_file = os.path.join(tide_dir,'CATS2008','hf.CATS2008.out') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = 'CATS2008' TYPE = 'z' elif (TIDE_MODEL == 'CATS2008_load'): grid_file = os.path.join(tide_dir,'CATS2008a_SPOTL_Load','grid_CATS2008a_opt') model_file = os.path.join(tide_dir,'CATS2008a_SPOTL_Load','h_CATS2008a_SPOTL_load') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') output_variable = 'tide_load' variable_long_name = 'Load_Tide' model_format = 'OTIS' EPSG = 'CATS2008' TYPE = 'z' elif (TIDE_MODEL == 'TPXO9-atlas'): model_directory = os.path.join(tide_dir,'TPXO9_atlas') grid_file = 'grid_tpxo9_atlas.nc.gz' model_files = ['h_q1_tpxo9_atlas_30.nc.gz','h_o1_tpxo9_atlas_30.nc.gz', 'h_p1_tpxo9_atlas_30.nc.gz','h_k1_tpxo9_atlas_30.nc.gz', 'h_n2_tpxo9_atlas_30.nc.gz','h_m2_tpxo9_atlas_30.nc.gz', 'h_s2_tpxo9_atlas_30.nc.gz','h_k2_tpxo9_atlas_30.nc.gz', 'h_m4_tpxo9_atlas_30.nc.gz','h_ms4_tpxo9_atlas_30.nc.gz', 'h_mn4_tpxo9_atlas_30.nc.gz','h_2n2_tpxo9_atlas_30.nc.gz'] reference = 'http://volkov.oce.orst.edu/tides/tpxo9_atlas.html' output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'netcdf' TYPE = 'z' SCALE = 1.0/1000.0 elif (TIDE_MODEL == 'TPXO9-atlas-v2'): model_directory = os.path.join(tide_dir,'TPXO9_atlas_v2') grid_file = 'grid_tpxo9_atlas_30_v2.nc.gz' model_files = ['h_q1_tpxo9_atlas_30_v2.nc.gz','h_o1_tpxo9_atlas_30_v2.nc.gz', 'h_p1_tpxo9_atlas_30_v2.nc.gz','h_k1_tpxo9_atlas_30_v2.nc.gz', 'h_n2_tpxo9_atlas_30_v2.nc.gz','h_m2_tpxo9_atlas_30_v2.nc.gz', 'h_s2_tpxo9_atlas_30_v2.nc.gz','h_k2_tpxo9_atlas_30_v2.nc.gz', 'h_m4_tpxo9_atlas_30_v2.nc.gz','h_ms4_tpxo9_atlas_30_v2.nc.gz', 'h_mn4_tpxo9_atlas_30_v2.nc.gz','h_2n2_tpxo9_atlas_30_v2.nc.gz'] reference = 'https://www.tpxo.net/global/tpxo9-atlas' output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'netcdf' TYPE = 'z' SCALE = 1.0/1000.0 elif (TIDE_MODEL == 'TPXO9-atlas-v3'): model_directory = os.path.join(tide_dir,'TPXO9_atlas_v3') grid_file = 'grid_tpxo9_atlas_30_v3.nc.gz' model_files = ['h_q1_tpxo9_atlas_30_v3.nc.gz','h_o1_tpxo9_atlas_30_v3.nc.gz', 'h_p1_tpxo9_atlas_30_v3.nc.gz','h_k1_tpxo9_atlas_30_v3.nc.gz', 'h_n2_tpxo9_atlas_30_v3.nc.gz','h_m2_tpxo9_atlas_30_v3.nc.gz', 'h_s2_tpxo9_atlas_30_v3.nc.gz','h_k2_tpxo9_atlas_30_v3.nc.gz', 'h_m4_tpxo9_atlas_30_v3.nc.gz','h_ms4_tpxo9_atlas_30_v3.nc.gz', 'h_mn4_tpxo9_atlas_30_v3.nc.gz','h_2n2_tpxo9_atlas_30_v3.nc.gz', 'h_mf_tpxo9_atlas_30_v3.nc.gz','h_mm_tpxo9_atlas_30_v3.nc.gz'] reference = 'https://www.tpxo.net/global/tpxo9-atlas' variable = 'tide_ocean' long_name = "Ocean_Tide" model_format = 'netcdf' TYPE = 'z' SCALE = 1.0/1000.0 elif (TIDE_MODEL == 'TPXO9.1'): grid_file = os.path.join(tide_dir,'TPXO9.1','DATA','grid_tpxo9') model_file = os.path.join(tide_dir,'TPXO9.1','DATA','h_tpxo9.v1') reference = 'http://volkov.oce.orst.edu/tides/global.html' output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO8-atlas'): grid_file = os.path.join(tide_dir,'tpxo8_atlas','grid_tpxo8atlas_30_v1') model_file = os.path.join(tide_dir,'tpxo8_atlas','hf.tpxo8_atlas_30_v1') reference = 'http://volkov.oce.orst.edu/tides/tpxo8_atlas.html' output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'ATLAS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO7.2'): grid_file = os.path.join(tide_dir,'TPXO7.2_tmd','grid_tpxo7.2') model_file = os.path.join(tide_dir,'TPXO7.2_tmd','h_tpxo7.2') reference = 'http://volkov.oce.orst.edu/tides/global.html' output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO7.2_load'): grid_file = os.path.join(tide_dir,'TPXO7.2_load','grid_tpxo6.2') model_file = os.path.join(tide_dir,'TPXO7.2_load','h_tpxo7.2_load') reference = 'http://volkov.oce.orst.edu/tides/global.html' output_variable = 'tide_load' variable_long_name = 'Load_Tide' model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'AODTM-5'): grid_file = os.path.join(tide_dir,'aodtm5_tmd','grid_Arc5km') model_file = os.path.join(tide_dir,'aodtm5_tmd','h0_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aodtm-5/') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'AOTIM-5'): grid_file = os.path.join(tide_dir,'aotim5_tmd','grid_Arc5km') model_file = os.path.join(tide_dir,'aotim5_tmd','h_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'AOTIM-5-2018'): grid_file = os.path.join(tide_dir,'Arc5km2018','grid_Arc5km2018') model_file = os.path.join(tide_dir,'Arc5km2018','h_Arc5km2018') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'GOT4.7'): model_directory = os.path.join(tide_dir,'GOT4.7','grids_oceantide') model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz', 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz'] c = ['q1','o1','p1','k1','n2','m2','s2','k2','s1','m4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'GOT' SCALE = 1.0/100.0 elif (TIDE_MODEL == 'GOT4.7_load'): model_directory = os.path.join(tide_dir,'GOT4.7','grids_loadtide') model_files = ['q1load.d.gz','o1load.d.gz','p1load.d.gz','k1load.d.gz', 'n2load.d.gz','m2load.d.gz','s2load.d.gz','k2load.d.gz', 's1load.d.gz','m4load.d.gz'] c = ['q1','o1','p1','k1','n2','m2','s2','k2','s1','m4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') output_variable = 'tide_load' variable_long_name = 'Load_Tide' model_format = 'GOT' SCALE = 1.0/1000.0 elif (TIDE_MODEL == 'GOT4.8'): model_directory = os.path.join(tide_dir,'got4.8','grids_oceantide') model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz', 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz'] c = ['q1','o1','p1','k1','n2','m2','s2','k2','s1','m4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'GOT' SCALE = 1.0/100.0 elif (TIDE_MODEL == 'GOT4.8_load'): model_directory = os.path.join(tide_dir,'got4.8','grids_loadtide') model_files = ['q1load.d.gz','o1load.d.gz','p1load.d.gz','k1load.d.gz', 'n2load.d.gz','m2load.d.gz','s2load.d.gz','k2load.d.gz', 's1load.d.gz','m4load.d.gz'] c = ['q1','o1','p1','k1','n2','m2','s2','k2','s1','m4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') output_variable = 'tide_load' variable_long_name = 'Load_Tide' model_format = 'GOT' SCALE = 1.0/1000.0 elif (TIDE_MODEL == 'GOT4.10'): model_directory = os.path.join(tide_dir,'GOT4.10c','grids_oceantide') model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz', 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz'] c = ['q1','o1','p1','k1','n2','m2','s2','k2','s1','m4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'GOT' SCALE = 1.0/100.0 elif (TIDE_MODEL == 'GOT4.10_load'): model_directory = os.path.join(tide_dir,'GOT4.10c','grids_loadtide') model_files = ['q1load.d.gz','o1load.d.gz','p1load.d.gz','k1load.d.gz', 'n2load.d.gz','m2load.d.gz','s2load.d.gz','k2load.d.gz', 's1load.d.gz','m4load.d.gz'] c = ['q1','o1','p1','k1','n2','m2','s2','k2','s1','m4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') output_variable = 'tide_load' variable_long_name = 'Load_Tide' model_format = 'GOT' SCALE = 1.0/1000.0 elif (TIDE_MODEL == 'FES2014'): model_directory = os.path.join(tide_dir,'fes2014','ocean_tide') model_files = ['2n2.nc.gz','eps2.nc.gz','j1.nc.gz','k1.nc.gz', 'k2.nc.gz','l2.nc.gz','la2.nc.gz','m2.nc.gz','m3.nc.gz','m4.nc.gz', 'm6.nc.gz','m8.nc.gz','mf.nc.gz','mks2.nc.gz','mm.nc.gz', 'mn4.nc.gz','ms4.nc.gz','msf.nc.gz','msqm.nc.gz','mtm.nc.gz', 'mu2.nc.gz','n2.nc.gz','n4.nc.gz','nu2.nc.gz','o1.nc.gz','p1.nc.gz', 'q1.nc.gz','r2.nc.gz','s1.nc.gz','s2.nc.gz','s4.nc.gz','sa.nc.gz', 'ssa.nc.gz','t2.nc.gz'] c = ['2n2','eps2','j1','k1','k2','l2','lambda2','m2','m3','m4','m6', 'm8','mf','mks2','mm','mn4','ms4','msf','msqm','mtm','mu2','n2', 'n4','nu2','o1','p1','q1','r2','s1','s2','s4','sa','ssa','t2'] reference = ('https://www.aviso.altimetry.fr/data/products/' 'auxiliary-products/global-tide-fes.html') output_variable = 'tide_ocean' variable_long_name = 'Ocean_Tide' model_format = 'FES' TYPE = 'z' SCALE = 1.0/100.0 elif (TIDE_MODEL == 'FES2014_load'): model_directory = os.path.join(tide_dir,'fes2014','load_tide') model_files = ['2n2.nc.gz','eps2.nc.gz','j1.nc.gz','k1.nc.gz', 'k2.nc.gz','l2.nc.gz','la2.nc.gz','m2.nc.gz','m3.nc.gz','m4.nc.gz', 'm6.nc.gz','m8.nc.gz','mf.nc.gz','mks2.nc.gz','mm.nc.gz', 'mn4.nc.gz','ms4.nc.gz','msf.nc.gz','msqm.nc.gz','mtm.nc.gz', 'mu2.nc.gz','n2.nc.gz','n4.nc.gz','nu2.nc.gz','o1.nc.gz','p1.nc.gz', 'q1.nc.gz','r2.nc.gz','s1.nc.gz','s2.nc.gz','s4.nc.gz','sa.nc.gz', 'ssa.nc.gz','t2.nc.gz'] c = ['2n2','eps2','j1','k1','k2','l2','lambda2','m2','m3','m4','m6', 'm8','mf','mks2','mm','mn4','ms4','msf','msqm','mtm','mu2','n2', 'n4','nu2','o1','p1','q1','r2','s1','s2','s4','sa','ssa','t2'] reference = ('https://www.aviso.altimetry.fr/data/products/' 'auxiliary-products/global-tide-fes.html') output_variable = 'tide_load' variable_long_name = 'Load_Tide' model_format = 'FES' TYPE = 'z' SCALE = 1.0/100.0 #-- invalid value fill_value = -9999.0 #-- output netCDF4 and HDF5 file attributes #-- will be added to YAML header in csv files attrib = {} #-- latitude attrib['lat'] = {} attrib['lat']['long_name'] = 'Latitude' attrib['lat']['units'] = 'Degrees_North' #-- longitude attrib['lon'] = {} attrib['lon']['long_name'] = 'Longitude' attrib['lon']['units'] = 'Degrees_East' #-- tides attrib[output_variable] = {} attrib[output_variable]['description'] = ('tidal_elevation_from_harmonic_' 'constants') attrib[output_variable]['model'] = TIDE_MODEL attrib[output_variable]['units'] = 'meters' attrib[output_variable]['long_name'] = variable_long_name attrib[output_variable]['_FillValue'] = fill_value #-- time attrib['time'] = {} attrib['time']['long_name'] = 'Time' attrib['time']['units'] = 'days since 1992-01-01T00:00:00' attrib['time']['calendar'] = 'standard' #-- read input file to extract time, spatial coordinates and data if (FORMAT == 'csv'): dinput = pyTMD.spatial.from_ascii(input_file, columns=VARIABLES, header=0, verbose=VERBOSE) elif (FORMAT == 'netCDF4'): dinput = pyTMD.spatial.from_netCDF4(input_file, timename=VARIABLES[0], xname=VARIABLES[2], yname=VARIABLES[1], varname=VARIABLES[3], verbose=VERBOSE) elif (FORMAT == 'HDF5'): dinput = pyTMD.spatial.from_HDF5(input_file, timename=VARIABLES[0], xname=VARIABLES[2], yname=VARIABLES[1], varname=VARIABLES[3], verbose=VERBOSE) #-- converting x,y from projection to latitude/longitude #-- could try to extract projection attributes from netCDF4 and HDF5 files try: crs1 = pyproj.CRS.from_string("epsg:{0:d}".format(int(PROJECTION))) except (ValueError,pyproj.exceptions.CRSError): crs1 = pyproj.CRS.from_string(PROJECTION) crs2 = pyproj.CRS.from_string("epsg:{0:d}".format(4326)) transformer = pyproj.Transformer.from_crs(crs1, crs2, always_xy=True) lon,lat = transformer.transform(dinput['x'].flatten(),dinput['y'].flatten()) #-- extract time units from netCDF4 and HDF5 attributes or from TIME_UNITS try: time_string = dinput['attributes']['time']['units'] except (TypeError, KeyError): epoch1,to_secs = pyTMD.time.parse_date_string(TIME_UNITS) else: epoch1,to_secs = pyTMD.time.parse_date_string(time_string) #-- convert time from units to days since 1992-01-01T00:00:00 tide_time = pyTMD.time.convert_delta_time(to_secs*dinput['time'].flatten(), epoch1=epoch1, epoch2=(1992,1,1,0,0,0), scale=1.0/86400.0) n_time = len(tide_time) #-- read tidal constants and interpolate to grid points if model_format in ('OTIS','ATLAS'): amp,ph,D,c = extract_tidal_constants(lon, lat, grid_file, model_file, EPSG, TYPE=TYPE, METHOD=METHOD) deltat = np.zeros((n_time)) elif (model_format == 'netcdf'): amp,ph,D,c = extract_netcdf_constants(lon, lat, model_directory, grid_file, model_files, TYPE=TYPE, METHOD=METHOD, SCALE=SCALE) deltat = np.zeros((n_time)) elif (model_format == 'GOT'): amp,ph = extract_GOT_constants(lon, lat, model_directory, model_files, METHOD=METHOD, SCALE=SCALE) #-- convert times from modified julian days to days since 1992-01-01 #-- interpolate delta times from calendar dates to tide time delta_file = get_data_path(['data','merged_deltat.data']) deltat = calc_delta_time(delta_file,tide_time) elif (model_format == 'FES'): amp,ph = extract_FES_constants(lon, lat, model_directory, model_files, TYPE=TYPE, VERSION=TIDE_MODEL, METHOD=METHOD, SCALE=SCALE) #-- convert times from modified julian days to days since 1992-01-01 #-- interpolate delta times from calendar dates to tide time delta_file = get_data_path(['data','merged_deltat.data']) deltat = calc_delta_time(delta_file,tide_time) #-- calculate complex phase in radians for Euler's cph = -1j*ph*np.pi/180.0 #-- calculate constituent oscillation hc = amp*np.exp(cph) #-- predict tidal elevations at time and infer minor corrections tide = np.ma.zeros((n_time), fill_value=fill_value) tide.mask = np.any(hc.mask,axis=1) tide.data[:] = predict_tide_drift(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model_format) minor = infer_minor_corrections(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model_format) tide.data[:] += minor.data[:] #-- replace invalid values with fill value tide.data[tide.mask] = tide.fill_value #-- output to file output = {'time':tide_time,'lon':lon,'lat':lat,output_variable:tide} if (FORMAT == 'csv'): pyTMD.spatial.to_ascii(output, attrib, output_file, delimiter=',', columns=['time','lat','lon',output_variable], verbose=VERBOSE) elif (FORMAT == 'netCDF4'): pyTMD.spatial.to_netCDF4(output, attrib, output_file, verbose=VERBOSE) elif (FORMAT == 'HDF5'): pyTMD.spatial.to_HDF5(output, attrib, output_file, verbose=VERBOSE) #-- change the permissions level to MODE os.chmod(output_file, MODE)
def compute_tides_ICESat2(tide_dir, INPUT_FILE, TIDE_MODEL=None, ATLAS_FORMAT=None, GZIP=True, DEFINITION_FILE=None, METHOD='spline', EXTRAPOLATE=False, CUTOFF=None, VERBOSE=False, MODE=0o775): #-- create logger for verbosity level loglevel = logging.INFO if VERBOSE else logging.CRITICAL logger = pyTMD.utilities.build_logger('pytmd', level=loglevel) #-- get parameters for tide model if DEFINITION_FILE is not None: model = pyTMD.model(tide_dir).from_file(DEFINITION_FILE) else: model = pyTMD.model(tide_dir, format=ATLAS_FORMAT, compressed=GZIP).elevation(TIDE_MODEL) #-- read data from input file logger.info('{0} -->'.format(INPUT_FILE)) IS2_atl10_mds, IS2_atl10_attrs, IS2_atl10_beams = read_HDF5_ATL10( INPUT_FILE, ATTRIBUTES=True) DIRECTORY = os.path.dirname(INPUT_FILE) #-- extract parameters from ICESat-2 ATLAS HDF5 sea ice file name rx = re.compile( r'(processed_)?(ATL\d{2})-(\d{2})_(\d{4})(\d{2})(\d{2})' r'(\d{2})(\d{2})(\d{2})_(\d{4})(\d{2})(\d{2})_(\d{3})_(\d{2})(.*?).h5$' ) try: SUB, PRD, HEM, YY, MM, DD, HH, MN, SS, TRK, CYCL, SN, RL, VERS, AUX = rx.findall( INPUT_FILE).pop() except: #-- output tide HDF5 file (generic) fileBasename, fileExtension = os.path.splitext(INPUT_FILE) args = (fileBasename, model.name, fileExtension) OUTPUT_FILE = '{0}_{1}_TIDES{2}'.format(*args) else: #-- output tide HDF5 file for ASAS/NSIDC granules args = (PRD, HEM, model.name, YY, MM, DD, HH, MN, SS, TRK, CYCL, SN, RL, VERS, AUX) ff = '{0}-{1}_{2}_TIDES_{3}{4}{5}{6}{7}{8}_{9}{10}{11}_{12}_{13}{14}.h5' OUTPUT_FILE = ff.format(*args) #-- number of GPS seconds between the GPS epoch #-- and ATLAS Standard Data Product (SDP) epoch atlas_sdp_gps_epoch = IS2_atl10_mds['ancillary_data'][ 'atlas_sdp_gps_epoch'] #-- delta time (TT - UT1) file delta_file = pyTMD.utilities.get_data_path(['data', 'merged_deltat.data']) #-- copy variables for outputting to HDF5 file IS2_atl10_tide = {} IS2_atl10_fill = {} IS2_atl10_dims = {} IS2_atl10_tide_attrs = {} #-- number of GPS seconds between the GPS epoch (1980-01-06T00:00:00Z UTC) #-- and ATLAS Standard Data Product (SDP) epoch (2018-01-01T00:00:00Z UTC) #-- Add this value to delta time parameters to compute full gps_seconds IS2_atl10_tide['ancillary_data'] = {} IS2_atl10_tide_attrs['ancillary_data'] = {} for key in ['atlas_sdp_gps_epoch']: #-- get each HDF5 variable IS2_atl10_tide['ancillary_data'][key] = IS2_atl10_mds[ 'ancillary_data'][key] #-- Getting attributes of group and included variables IS2_atl10_tide_attrs['ancillary_data'][key] = {} for att_name, att_val in IS2_atl10_attrs['ancillary_data'][key].items( ): IS2_atl10_tide_attrs['ancillary_data'][key][att_name] = att_val #-- for each input beam within the file for gtx in sorted(IS2_atl10_beams): #-- output data dictionaries for beam IS2_atl10_tide[gtx] = dict(freeboard_beam_segment={}, leads={}) IS2_atl10_fill[gtx] = dict(freeboard_beam_segment={}, leads={}) IS2_atl10_dims[gtx] = dict(freeboard_beam_segment={}, leads={}) IS2_atl10_tide_attrs[gtx] = dict(freeboard_beam_segment={}, leads={}) #-- group attributes for beam IS2_atl10_tide_attrs[gtx]['Description'] = IS2_atl10_attrs[gtx][ 'Description'] IS2_atl10_tide_attrs[gtx]['atlas_pce'] = IS2_atl10_attrs[gtx][ 'atlas_pce'] IS2_atl10_tide_attrs[gtx]['atlas_beam_type'] = IS2_atl10_attrs[gtx][ 'atlas_beam_type'] IS2_atl10_tide_attrs[gtx]['groundtrack_id'] = IS2_atl10_attrs[gtx][ 'groundtrack_id'] IS2_atl10_tide_attrs[gtx]['atmosphere_profile'] = IS2_atl10_attrs[gtx][ 'atmosphere_profile'] IS2_atl10_tide_attrs[gtx]['atlas_spot_number'] = IS2_atl10_attrs[gtx][ 'atlas_spot_number'] IS2_atl10_tide_attrs[gtx]['sc_orientation'] = IS2_atl10_attrs[gtx][ 'sc_orientation'] #-- group attributes for freeboard_beam_segment IS2_atl10_tide_attrs[gtx]['freeboard_beam_segment']['Description'] = ( "Contains freeboard " "estimate and associated height segment parameters for only the sea ice segments by beam." ) IS2_atl10_tide_attrs[gtx]['freeboard_beam_segment']['data_rate'] = ( "Data within this " "group are stored at the freeboard swath segment rate.") #-- group attributes for leads IS2_atl10_tide_attrs[gtx]['leads']['Description'] = ( "Contains parameters relating " "to the freeboard values.") IS2_atl10_tide_attrs[gtx]['leads']['data_rate'] = ( "Data within this " "group are stored at the lead index rate.") #-- for each ATL10 group for group in ['freeboard_beam_segment', 'leads']: #-- number of segments val = IS2_atl10_mds[gtx][group] n_seg = len(val['delta_time']) #-- convert time from ATLAS SDP to days relative to Jan 1, 1992 gps_seconds = atlas_sdp_gps_epoch + val['delta_time'] leap_seconds = pyTMD.time.count_leap_seconds(gps_seconds) tide_time = pyTMD.time.convert_delta_time( gps_seconds - leap_seconds, epoch1=(1980, 1, 6, 0, 0, 0), epoch2=(1992, 1, 1, 0, 0, 0), scale=1.0 / 86400.0) #-- read tidal constants and interpolate to grid points if model.format in ('OTIS', 'ATLAS'): amp, ph, D, c = extract_tidal_constants( val['longitude'], val['latitude'], model.grid_file, model.model_file, model.projection, TYPE=model.type, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, GRID=model.format) deltat = np.zeros_like(tide_time) elif (model.format == 'netcdf'): amp, ph, D, c = extract_netcdf_constants( val['longitude'], val['latitude'], model.grid_file, model.model_file, TYPE=model.type, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=model.scale, CUTOFF=CUTOFF, GZIP=model.compressed) deltat = np.zeros_like(tide_time) elif (model.format == 'GOT'): amp, ph, c = extract_GOT_constants(val['longitude'], val['latitude'], model.model_file, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, tide_time) elif (model.format == 'FES'): amp, ph = extract_FES_constants(val['longitude'], val['latitude'], model.model_file, TYPE=model.type, VERSION=model.version, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=model.scale, GZIP=model.compressed) #-- available model constituents c = model.constituents #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, tide_time) #-- calculate complex phase in radians for Euler's cph = -1j * ph * np.pi / 180.0 #-- calculate constituent oscillation hc = amp * np.exp(cph) #-- predict tidal elevations at time and infer minor corrections tide = np.ma.empty((n_seg)) tide.mask = np.any(hc.mask, axis=1) tide.data[:] = predict_tide_drift(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model.format) minor = infer_minor_corrections(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model.format) tide.data[:] += minor.data[:] #-- replace masked and nan values with fill value invalid, = np.nonzero(np.isnan(tide.data) | tide.mask) tide.data[invalid] = tide.fill_value tide.mask[invalid] = True #-- geolocation, time and segment ID #-- delta time IS2_atl10_tide[gtx][group]['delta_time'] = val['delta_time'].copy() IS2_atl10_fill[gtx][group]['delta_time'] = None IS2_atl10_dims[gtx][group]['delta_time'] = None IS2_atl10_tide_attrs[gtx][group]['delta_time'] = {} IS2_atl10_tide_attrs[gtx][group]['delta_time'][ 'units'] = "seconds since 2018-01-01" IS2_atl10_tide_attrs[gtx][group]['delta_time'][ 'long_name'] = "Elapsed GPS seconds" IS2_atl10_tide_attrs[gtx][group]['delta_time'][ 'standard_name'] = "time" IS2_atl10_tide_attrs[gtx][group]['delta_time'][ 'source'] = "telemetry" IS2_atl10_tide_attrs[gtx][group]['delta_time'][ 'calendar'] = "standard" IS2_atl10_tide_attrs[gtx][group]['delta_time']['description'] = ( "Number of " "GPS seconds since the ATLAS SDP epoch. The ATLAS Standard Data Products (SDP) epoch " "offset is defined within /ancillary_data/atlas_sdp_gps_epoch as the number of GPS " "seconds between the GPS epoch (1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP " "epoch. By adding the offset contained within atlas_sdp_gps_epoch to delta time " "parameters, the time in gps_seconds relative to the GPS epoch can be computed." ) IS2_atl10_tide_attrs[gtx][group]['delta_time']['coordinates'] = \ "latitude longitude" #-- latitude IS2_atl10_tide[gtx][group]['latitude'] = val['latitude'].copy() IS2_atl10_fill[gtx][group]['latitude'] = None IS2_atl10_dims[gtx][group]['latitude'] = ['delta_time'] IS2_atl10_tide_attrs[gtx][group]['latitude'] = {} IS2_atl10_tide_attrs[gtx][group]['latitude'][ 'units'] = "degrees_north" IS2_atl10_tide_attrs[gtx][group]['latitude'][ 'contentType'] = "physicalMeasurement" IS2_atl10_tide_attrs[gtx][group]['latitude'][ 'long_name'] = "Latitude" IS2_atl10_tide_attrs[gtx][group]['latitude'][ 'standard_name'] = "latitude" IS2_atl10_tide_attrs[gtx][group]['latitude']['description'] = ( "Latitude of " "segment center") IS2_atl10_tide_attrs[gtx][group]['latitude']['valid_min'] = -90.0 IS2_atl10_tide_attrs[gtx][group]['latitude']['valid_max'] = 90.0 IS2_atl10_tide_attrs[gtx][group]['latitude']['coordinates'] = \ "delta_time longitude" #-- longitude IS2_atl10_tide[gtx][group]['longitude'] = val['longitude'].copy() IS2_atl10_fill[gtx][group]['longitude'] = None IS2_atl10_dims[gtx][group]['longitude'] = ['delta_time'] IS2_atl10_tide_attrs[gtx][group]['longitude'] = {} IS2_atl10_tide_attrs[gtx][group]['longitude'][ 'units'] = "degrees_east" IS2_atl10_tide_attrs[gtx][group]['longitude'][ 'contentType'] = "physicalMeasurement" IS2_atl10_tide_attrs[gtx][group]['longitude'][ 'long_name'] = "Longitude" IS2_atl10_tide_attrs[gtx][group]['longitude'][ 'standard_name'] = "longitude" IS2_atl10_tide_attrs[gtx][group]['longitude']['description'] = ( "Longitude of " "segment center") IS2_atl10_tide_attrs[gtx][group]['longitude']['valid_min'] = -180.0 IS2_atl10_tide_attrs[gtx][group]['longitude']['valid_max'] = 180.0 IS2_atl10_tide_attrs[gtx][group]['longitude']['coordinates'] = \ "delta_time latitude" #-- geophysical variables IS2_atl10_tide[gtx][group]['geophysical'] = {} IS2_atl10_fill[gtx][group]['geophysical'] = {} IS2_atl10_dims[gtx][group]['geophysical'] = {} IS2_atl10_tide_attrs[gtx][group]['geophysical'] = {} IS2_atl10_tide_attrs[gtx][group]['geophysical']['Description'] = ( "Contains geophysical " "parameters and corrections used to correct photon heights for geophysical effects, " "such as tides.") IS2_atl10_tide_attrs[gtx][group]['geophysical']['data_rate'] = ( "Data within this group " "are stored at the variable segment rate.") #-- computed tide IS2_atl10_tide[gtx][group]['geophysical'][ model.atl10] = tide.copy() IS2_atl10_fill[gtx][group]['geophysical'][ model.atl10] = tide.fill_value IS2_atl10_dims[gtx][group]['geophysical'][model.atl10] = [ 'delta_time' ] IS2_atl10_tide_attrs[gtx][group]['geophysical'][model.atl10] = {} IS2_atl10_tide_attrs[gtx][group]['geophysical'][ model.atl10]['units'] = "meters" IS2_atl10_tide_attrs[gtx][group]['geophysical'][model.atl10]['contentType'] = \ "referenceInformation" IS2_atl10_tide_attrs[gtx][group]['geophysical'][ model.atl10]['long_name'] = model.long_name IS2_atl10_tide_attrs[gtx][group]['geophysical'][ model.atl10]['description'] = model.description IS2_atl10_tide_attrs[gtx][group]['geophysical'][ model.atl10]['source'] = model.name IS2_atl10_tide_attrs[gtx][group]['geophysical'][ model.atl10]['reference'] = model.reference IS2_atl10_tide_attrs[gtx][group]['geophysical'][model.atl10]['coordinates'] = \ "../delta_time ../latitude ../longitude" #-- print file information logger.info('\t{0}'.format(OUTPUT_FILE)) HDF5_ATL10_tide_write(IS2_atl10_tide, IS2_atl10_tide_attrs, CLOBBER=True, INPUT=os.path.basename(INPUT_FILE), FILL_VALUE=IS2_atl10_fill, DIMENSIONS=IS2_atl10_dims, FILENAME=os.path.join(DIRECTORY, OUTPUT_FILE)) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY, OUTPUT_FILE), MODE)
def compute_tides_ICESat2(tide_dir, FILE, TIDE_MODEL=None, METHOD='spline', EXTRAPOLATE=False, VERBOSE=False, MODE=0o775): #-- select between tide models if (TIDE_MODEL == 'CATS0201'): grid_file = os.path.join(tide_dir,'cats0201_tmd','grid_CATS') model_file = os.path.join(tide_dir,'cats0201_tmd','h0_CATS02_01') reference = 'https://mail.esr.org/polar_tide_models/Model_CATS0201.html' variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'CATS2008'): grid_file = os.path.join(tide_dir,'CATS2008','grid_CATS2008') model_file = os.path.join(tide_dir,'CATS2008','hf.CATS2008.out') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = 'CATS2008' TYPE = 'z' elif (TIDE_MODEL == 'CATS2008_load'): grid_file = os.path.join(tide_dir,'CATS2008a_SPOTL_Load','grid_CATS2008a_opt') model_file = os.path.join(tide_dir,'CATS2008a_SPOTL_Load','h_CATS2008a_SPOTL_load') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') variable = 'height_segment_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'OTIS' EPSG = 'CATS2008' TYPE = 'z' elif (TIDE_MODEL == 'TPXO9-atlas'): model_directory = os.path.join(tide_dir,'TPXO9_atlas') grid_file = os.path.join(model_directory,'grid_tpxo9_atlas.nc.gz') model_files = ['h_q1_tpxo9_atlas_30.nc.gz','h_o1_tpxo9_atlas_30.nc.gz', 'h_p1_tpxo9_atlas_30.nc.gz','h_k1_tpxo9_atlas_30.nc.gz', 'h_n2_tpxo9_atlas_30.nc.gz','h_m2_tpxo9_atlas_30.nc.gz', 'h_s2_tpxo9_atlas_30.nc.gz','h_k2_tpxo9_atlas_30.nc.gz', 'h_m4_tpxo9_atlas_30.nc.gz','h_ms4_tpxo9_atlas_30.nc.gz', 'h_mn4_tpxo9_atlas_30.nc.gz','h_2n2_tpxo9_atlas_30.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = 'http://volkov.oce.orst.edu/tides/tpxo9_atlas.html' variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'netcdf' TYPE = 'z' SCALE = 1.0/1000.0 GZIP = True elif (TIDE_MODEL == 'TPXO9-atlas-v2'): model_directory = os.path.join(tide_dir,'TPXO9_atlas_v2') grid_file = os.path.join(model_directory,'grid_tpxo9_atlas_30_v2.nc.gz') model_files = ['h_q1_tpxo9_atlas_30_v2.nc.gz','h_o1_tpxo9_atlas_30_v2.nc.gz', 'h_p1_tpxo9_atlas_30_v2.nc.gz','h_k1_tpxo9_atlas_30_v2.nc.gz', 'h_n2_tpxo9_atlas_30_v2.nc.gz','h_m2_tpxo9_atlas_30_v2.nc.gz', 'h_s2_tpxo9_atlas_30_v2.nc.gz','h_k2_tpxo9_atlas_30_v2.nc.gz', 'h_m4_tpxo9_atlas_30_v2.nc.gz','h_ms4_tpxo9_atlas_30_v2.nc.gz', 'h_mn4_tpxo9_atlas_30_v2.nc.gz','h_2n2_tpxo9_atlas_30_v2.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = 'https://www.tpxo.net/global/tpxo9-atlas' variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'netcdf' TYPE = 'z' SCALE = 1.0/1000.0 GZIP = True elif (TIDE_MODEL == 'TPXO9-atlas-v3'): model_directory = os.path.join(tide_dir,'TPXO9_atlas_v3') grid_file = os.path.join(model_directory,'grid_tpxo9_atlas_30_v3.nc.gz') model_files = ['h_q1_tpxo9_atlas_30_v3.nc.gz','h_o1_tpxo9_atlas_30_v3.nc.gz', 'h_p1_tpxo9_atlas_30_v3.nc.gz','h_k1_tpxo9_atlas_30_v3.nc.gz', 'h_n2_tpxo9_atlas_30_v3.nc.gz','h_m2_tpxo9_atlas_30_v3.nc.gz', 'h_s2_tpxo9_atlas_30_v3.nc.gz','h_k2_tpxo9_atlas_30_v3.nc.gz', 'h_m4_tpxo9_atlas_30_v3.nc.gz','h_ms4_tpxo9_atlas_30_v3.nc.gz', 'h_mn4_tpxo9_atlas_30_v3.nc.gz','h_2n2_tpxo9_atlas_30_v3.nc.gz', 'h_mf_tpxo9_atlas_30_v3.nc.gz','h_mm_tpxo9_atlas_30_v3.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = 'https://www.tpxo.net/global/tpxo9-atlas' variable = 'tide_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'netcdf' TYPE = 'z' SCALE = 1.0/1000.0 GZIP = True elif (TIDE_MODEL == 'TPXO9-atlas-v4'): model_directory = os.path.join(tide_dir,'TPXO9_atlas_v4') grid_file = os.path.join(model_directory,'grid_tpxo9_atlas_30_v4') model_files = ['h_q1_tpxo9_atlas_30_v4','h_o1_tpxo9_atlas_30_v4', 'h_p1_tpxo9_atlas_30_v4','h_k1_tpxo9_atlas_30_v4', 'h_n2_tpxo9_atlas_30_v4','h_m2_tpxo9_atlas_30_v4', 'h_s2_tpxo9_atlas_30_v4','h_k2_tpxo9_atlas_30_v4', 'h_m4_tpxo9_atlas_30_v4','h_ms4_tpxo9_atlas_30_v4', 'h_mn4_tpxo9_atlas_30_v4','h_2n2_tpxo9_atlas_30_v4', 'h_mf_tpxo9_atlas_30_v4','h_mm_tpxo9_atlas_30_v4'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = 'https://www.tpxo.net/global/tpxo9-atlas' variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO9.1'): grid_file = os.path.join(tide_dir,'TPXO9.1','DATA','grid_tpxo9') model_file = os.path.join(tide_dir,'TPXO9.1','DATA','h_tpxo9.v1') reference = 'http://volkov.oce.orst.edu/tides/global.html' variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO8-atlas'): grid_file = os.path.join(tide_dir,'tpxo8_atlas','grid_tpxo8atlas_30_v1') model_file = os.path.join(tide_dir,'tpxo8_atlas','hf.tpxo8_atlas_30_v1') reference = 'http://volkov.oce.orst.edu/tides/tpxo8_atlas.html' variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'ATLAS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO7.2'): grid_file = os.path.join(tide_dir,'TPXO7.2_tmd','grid_tpxo7.2') model_file = os.path.join(tide_dir,'TPXO7.2_tmd','h_tpxo7.2') reference = 'http://volkov.oce.orst.edu/tides/global.html' variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO7.2_load'): grid_file = os.path.join(tide_dir,'TPXO7.2_load','grid_tpxo6.2') model_file = os.path.join(tide_dir,'TPXO7.2_load','h_tpxo7.2_load') reference = 'http://volkov.oce.orst.edu/tides/global.html' variable = 'height_segment_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'AODTM-5'): grid_file = os.path.join(tide_dir,'aodtm5_tmd','grid_Arc5km') model_file = os.path.join(tide_dir,'aodtm5_tmd','h0_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aodtm-5/') variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'AOTIM-5'): grid_file = os.path.join(tide_dir,'aotim5_tmd','grid_Arc5km') model_file = os.path.join(tide_dir,'aotim5_tmd','h_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'AOTIM-5-2018'): grid_file = os.path.join(tide_dir,'Arc5km2018','grid_Arc5km2018') model_file = os.path.join(tide_dir,'Arc5km2018','h_Arc5km2018') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') variable = 'tide_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'GOT4.7'): model_directory = os.path.join(tide_dir,'GOT4.7','grids_oceantide') model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz', 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'GOT' SCALE = 1.0/100.0 GZIP = True elif (TIDE_MODEL == 'GOT4.7_load'): model_directory = os.path.join(tide_dir,'GOT4.7','grids_loadtide') model_files = ['q1load.d.gz','o1load.d.gz','p1load.d.gz','k1load.d.gz', 'n2load.d.gz','m2load.d.gz','s2load.d.gz','k2load.d.gz', 's1load.d.gz','m4load.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'height_segment_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'GOT' SCALE = 1.0/1000.0 GZIP = True elif (TIDE_MODEL == 'GOT4.8'): model_directory = os.path.join(tide_dir,'got4.8','grids_oceantide') model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz', 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'GOT' SCALE = 1.0/100.0 GZIP = True elif (TIDE_MODEL == 'GOT4.8_load'): model_directory = os.path.join(tide_dir,'got4.8','grids_loadtide') model_files = ['q1load.d.gz','o1load.d.gz','p1load.d.gz','k1load.d.gz', 'n2load.d.gz','m2load.d.gz','s2load.d.gz','k2load.d.gz', 's1load.d.gz','m4load.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'height_segment_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'GOT' SCALE = 1.0/1000.0 GZIP = True elif (TIDE_MODEL == 'GOT4.10'): model_directory = os.path.join(tide_dir,'GOT4.10c','grids_oceantide') model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz', 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'GOT' SCALE = 1.0/100.0 GZIP = True elif (TIDE_MODEL == 'GOT4.10_load'): model_directory = os.path.join(tide_dir,'GOT4.10c','grids_loadtide') model_files = ['q1load.d.gz','o1load.d.gz','p1load.d.gz','k1load.d.gz', 'n2load.d.gz','m2load.d.gz','s2load.d.gz','k2load.d.gz', 's1load.d.gz','m4load.d.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'height_segment_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'GOT' SCALE = 1.0/1000.0 GZIP = True elif (TIDE_MODEL == 'FES2014'): model_directory = os.path.join(tide_dir,'fes2014','ocean_tide') model_files = ['2n2.nc.gz','eps2.nc.gz','j1.nc.gz','k1.nc.gz', 'k2.nc.gz','l2.nc.gz','la2.nc.gz','m2.nc.gz','m3.nc.gz','m4.nc.gz', 'm6.nc.gz','m8.nc.gz','mf.nc.gz','mks2.nc.gz','mm.nc.gz', 'mn4.nc.gz','ms4.nc.gz','msf.nc.gz','msqm.nc.gz','mtm.nc.gz', 'mu2.nc.gz','n2.nc.gz','n4.nc.gz','nu2.nc.gz','o1.nc.gz','p1.nc.gz', 'q1.nc.gz','r2.nc.gz','s1.nc.gz','s2.nc.gz','s4.nc.gz','sa.nc.gz', 'ssa.nc.gz','t2.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] c = ['2n2','eps2','j1','k1','k2','l2','lambda2','m2','m3','m4','m6', 'm8','mf','mks2','mm','mn4','ms4','msf','msqm','mtm','mu2','n2', 'n4','nu2','o1','p1','q1','r2','s1','s2','s4','sa','ssa','t2'] reference = ('https://www.aviso.altimetry.fr/en/data/products' 'auxiliary-products/global-tide-fes.html') variable = 'height_segment_ocean' long_name = "Ocean Tide" description = ("Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'FES' TYPE = 'z' SCALE = 1.0/100.0 GZIP = True elif (TIDE_MODEL == 'FES2014_load'): model_directory = os.path.join(tide_dir,'fes2014','load_tide') model_files = ['2n2.nc.gz','eps2.nc.gz','j1.nc.gz','k1.nc.gz', 'k2.nc.gz','l2.nc.gz','la2.nc.gz','m2.nc.gz','m3.nc.gz','m4.nc.gz', 'm6.nc.gz','m8.nc.gz','mf.nc.gz','mks2.nc.gz','mm.nc.gz', 'mn4.nc.gz','ms4.nc.gz','msf.nc.gz','msqm.nc.gz','mtm.nc.gz', 'mu2.nc.gz','n2.nc.gz','n4.nc.gz','nu2.nc.gz','o1.nc.gz','p1.nc.gz', 'q1.nc.gz','r2.nc.gz','s1.nc.gz','s2.nc.gz','s4.nc.gz','sa.nc.gz', 'ssa.nc.gz','t2.nc.gz'] model_file = [os.path.join(model_directory,m) for m in model_files] c = ['2n2','eps2','j1','k1','k2','l2','lambda2','m2','m3','m4','m6', 'm8','mf','mks2','mm','mn4','ms4','msf','msqm','mtm','mu2','n2', 'n4','nu2','o1','p1','q1','r2','s1','s2','s4','sa','ssa','t2'] reference = ('https://www.aviso.altimetry.fr/en/data/products' 'auxiliary-products/global-tide-fes.html') variable = 'height_segment_load' long_name = "Load Tide" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'FES' TYPE = 'z' SCALE = 1.0/100.0 GZIP = True #-- read data from FILE print('{0} -->'.format(os.path.basename(FILE))) if VERBOSE else None IS2_atl07_mds,IS2_atl07_attrs,IS2_atl07_beams = read_HDF5_ATL07(FILE, ATTRIBUTES=True) DIRECTORY = os.path.dirname(FILE) #-- extract parameters from ICESat-2 ATLAS HDF5 sea ice file name rx = re.compile(r'(processed_)?(ATL\d{2})-(\d{2})_(\d{4})(\d{2})(\d{2})' r'(\d{2})(\d{2})(\d{2})_(\d{4})(\d{2})(\d{2})_(\d{3})_(\d{2})(.*?).h5$') SUB,PRD,HEM,YY,MM,DD,HH,MN,SS,TRK,CYCL,SN,RL,VERS,AUX=rx.findall(FILE).pop() #-- number of GPS seconds between the GPS epoch #-- and ATLAS Standard Data Product (SDP) epoch atlas_sdp_gps_epoch = IS2_atl07_mds['ancillary_data']['atlas_sdp_gps_epoch'] #-- delta time (TT - UT1) file delta_file = pyTMD.utilities.get_data_path(['data','merged_deltat.data']) #-- copy variables for outputting to HDF5 file IS2_atl07_tide = {} IS2_atl07_fill = {} IS2_atl07_dims = {} IS2_atl07_tide_attrs = {} #-- number of GPS seconds between the GPS epoch (1980-01-06T00:00:00Z UTC) #-- and ATLAS Standard Data Product (SDP) epoch (2018-01-01T00:00:00Z UTC) #-- Add this value to delta time parameters to compute full gps_seconds IS2_atl07_tide['ancillary_data'] = {} IS2_atl07_tide_attrs['ancillary_data'] = {} for key in ['atlas_sdp_gps_epoch']: #-- get each HDF5 variable IS2_atl07_tide['ancillary_data'][key] = IS2_atl07_mds['ancillary_data'][key] #-- Getting attributes of group and included variables IS2_atl07_tide_attrs['ancillary_data'][key] = {} for att_name,att_val in IS2_atl07_attrs['ancillary_data'][key].items(): IS2_atl07_tide_attrs['ancillary_data'][key][att_name] = att_val #-- for each input beam within the file for gtx in sorted(IS2_atl07_beams): #-- output data dictionaries for beam IS2_atl07_tide[gtx] = dict(sea_ice_segments={}) IS2_atl07_fill[gtx] = dict(sea_ice_segments={}) IS2_atl07_dims[gtx] = dict(sea_ice_segments={}) IS2_atl07_tide_attrs[gtx] = dict(sea_ice_segments={}) #-- number of segments val = IS2_atl07_mds[gtx]['sea_ice_segments'] n_seg = len(val['height_segment_id']) #-- convert time from ATLAS SDP to days relative to Jan 1, 1992 gps_seconds = atlas_sdp_gps_epoch + val['delta_time'] leap_seconds = pyTMD.time.count_leap_seconds(gps_seconds) tide_time = pyTMD.time.convert_delta_time(gps_seconds-leap_seconds, epoch1=(1980,1,6,0,0,0), epoch2=(1992,1,1,0,0,0), scale=1.0/86400.0) #-- read tidal constants and interpolate to grid points if model_format in ('OTIS','ATLAS'): amp,ph,D,c = extract_tidal_constants(val['longitude'], val['latitude'], grid_file, model_file, EPSG, TYPE=TYPE, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, GRID=model_format) deltat = np.zeros_like(tide_time) elif (model_format == 'netcdf'): amp,ph,D,c = extract_netcdf_constants(val['longitude'], val['latitude'], grid_file, model_file, TYPE=TYPE, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=SCALE, GZIP=GZIP) deltat = np.zeros_like(tide_time) elif (model_format == 'GOT'): amp,ph,c = extract_GOT_constants(val['longitude'], val['latitude'], model_file, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=SCALE, GZIP=GZIP) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, tide_time) elif (model_format == 'FES'): amp,ph = extract_FES_constants(val['longitude'], val['latitude'], model_file, TYPE=TYPE, VERSION=TIDE_MODEL, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, SCALE=SCALE, GZIP=GZIP) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, tide_time) #-- calculate complex phase in radians for Euler's cph = -1j*ph*np.pi/180.0 #-- calculate constituent oscillation hc = amp*np.exp(cph) #-- predict tidal elevations at time and infer minor corrections tide = np.ma.empty((n_seg)) tide.mask = np.any(hc.mask,axis=1) tide.data[:] = predict_tide_drift(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model_format) minor = infer_minor_corrections(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model_format) tide.data[:] += minor.data[:] #-- replace masked and nan values with fill value invalid, = np.nonzero(np.isnan(tide.data) | tide.mask) tide.data[invalid] = tide.fill_value tide.mask[invalid] = True #-- group attributes for beam IS2_atl07_tide_attrs[gtx]['Description'] = IS2_atl07_attrs[gtx]['Description'] IS2_atl07_tide_attrs[gtx]['atlas_pce'] = IS2_atl07_attrs[gtx]['atlas_pce'] IS2_atl07_tide_attrs[gtx]['atlas_beam_type'] = IS2_atl07_attrs[gtx]['atlas_beam_type'] IS2_atl07_tide_attrs[gtx]['groundtrack_id'] = IS2_atl07_attrs[gtx]['groundtrack_id'] IS2_atl07_tide_attrs[gtx]['atmosphere_profile'] = IS2_atl07_attrs[gtx]['atmosphere_profile'] IS2_atl07_tide_attrs[gtx]['atlas_spot_number'] = IS2_atl07_attrs[gtx]['atlas_spot_number'] IS2_atl07_tide_attrs[gtx]['sc_orientation'] = IS2_atl07_attrs[gtx]['sc_orientation'] #-- group attributes for sea_ice_segments IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['Description'] = ("Top group for sea " "ice segments as computed by the ATBD algorithm.") IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['data_rate'] = ("Data within this " "group are stored at the variable segment rate.") #-- geolocation, time and segment ID #-- delta time IS2_atl07_tide[gtx]['sea_ice_segments']['delta_time'] = val['delta_time'].copy() IS2_atl07_fill[gtx]['sea_ice_segments']['delta_time'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['delta_time'] = None IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time']['units'] = "seconds since 2018-01-01" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time']['long_name'] = "Elapsed GPS seconds" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time']['standard_name'] = "time" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time']['source'] = "telemetry" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time']['calendar'] = "standard" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time']['description'] = ("Number of " "GPS seconds since the ATLAS SDP epoch. The ATLAS Standard Data Products (SDP) epoch " "offset is defined within /ancillary_data/atlas_sdp_gps_epoch as the number of GPS " "seconds between the GPS epoch (1980-01-06T00:00:00.000000Z UTC) and the ATLAS SDP " "epoch. By adding the offset contained within atlas_sdp_gps_epoch to delta time " "parameters, the time in gps_seconds relative to the GPS epoch can be computed.") IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['delta_time']['coordinates'] = \ "height_segment_id latitude longitude" #-- latitude IS2_atl07_tide[gtx]['sea_ice_segments']['latitude'] = val['latitude'].copy() IS2_atl07_fill[gtx]['sea_ice_segments']['latitude'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['latitude'] = ['delta_time'] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude']['units'] = "degrees_north" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude']['contentType'] = "physicalMeasurement" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude']['long_name'] = "Latitude" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude']['standard_name'] = "latitude" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude']['description'] = ("Latitude of " "segment center") IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude']['valid_min'] = -90.0 IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude']['valid_max'] = 90.0 IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['latitude']['coordinates'] = \ "height_segment_id delta_time longitude" #-- longitude IS2_atl07_tide[gtx]['sea_ice_segments']['longitude'] = val['longitude'].copy() IS2_atl07_fill[gtx]['sea_ice_segments']['longitude'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['longitude'] = ['delta_time'] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude']['units'] = "degrees_east" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude']['contentType'] = "physicalMeasurement" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude']['long_name'] = "Longitude" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude']['standard_name'] = "longitude" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude']['description'] = ("Longitude of " "segment center") IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude']['valid_min'] = -180.0 IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude']['valid_max'] = 180.0 IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['longitude']['coordinates'] = \ "height_segment_id delta_time latitude" #-- segment ID IS2_atl07_tide[gtx]['sea_ice_segments']['height_segment_id'] = val['height_segment_id'] IS2_atl07_fill[gtx]['sea_ice_segments']['height_segment_id'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['height_segment_id'] = ['delta_time'] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['height_segment_id'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['height_segment_id']['units'] = "1" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['height_segment_id']['contentType'] = "referenceInformation" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['height_segment_id']['long_name'] = \ "Identifier of each height segment" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['height_segment_id']['description'] = \ "Identifier of each height segment" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['height_segment_id']['coordinates'] = \ "delta_time latitude longitude" #-- geolocation segment beginning IS2_atl07_tide[gtx]['sea_ice_segments']['geoseg_beg'] = val['geoseg_beg'].copy() IS2_atl07_fill[gtx]['sea_ice_segments']['geoseg_beg'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['geoseg_beg'] = ['delta_time'] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_beg'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_beg']['units'] = "1" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_beg']['contentType'] = "referenceInformation" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_beg']['long_name'] = "Beginning GEOSEG" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_beg']['description'] = \ "Geolocation segment (geoseg) ID associated with the first photon used in this sea ice segment" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_beg']['coordinates'] = \ "height_segment_id delta_time latitude longitude" #-- geolocation segment ending IS2_atl07_tide[gtx]['sea_ice_segments']['geoseg_end'] = val['geoseg_end'].copy() IS2_atl07_fill[gtx]['sea_ice_segments']['geoseg_end'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['geoseg_end'] = ['delta_time'] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_end'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_end']['units'] = "1" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_end']['contentType'] = "referenceInformation" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_end']['long_name'] = "Ending GEOSEG" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_end']['description'] = \ "Geolocation segment (geoseg) ID associated with the last photon used in this sea ice segment" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geoseg_end']['coordinates'] = \ "height_segment_id delta_time latitude longitude" #-- along track distance IS2_atl07_tide[gtx]['sea_ice_segments']['seg_dist_x'] = val['seg_dist_x'].copy() IS2_atl07_fill[gtx]['sea_ice_segments']['seg_dist_x'] = None IS2_atl07_dims[gtx]['sea_ice_segments']['seg_dist_x'] = ['delta_time'] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['seg_dist_x'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['seg_dist_x']['units'] = "meters" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['seg_dist_x']['contentType'] = "referenceInformation" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['seg_dist_x']['long_name'] = "Along track distance" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['seg_dist_x']['description'] = \ "Along-track distance from the equator crossing to the segment center." IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['seg_dist_x']['coordinates'] = \ "height_segment_id delta_time latitude longitude" #-- geophysical variables IS2_atl07_tide[gtx]['sea_ice_segments']['geophysical'] = {} IS2_atl07_fill[gtx]['sea_ice_segments']['geophysical'] = {} IS2_atl07_dims[gtx]['sea_ice_segments']['geophysical'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical']['Description'] = ("Contains geophysical " "parameters and corrections used to correct photon heights for geophysical effects, such as tides.") IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical']['data_rate'] = ("Data within this group " "are stored at the sea_ice_height segment rate.") #-- computed tide IS2_atl07_tide[gtx]['sea_ice_segments']['geophysical'][variable] = tide.copy() IS2_atl07_fill[gtx]['sea_ice_segments']['geophysical'][variable] = tide.fill_value IS2_atl07_dims[gtx]['sea_ice_segments']['geophysical'][variable] = ['delta_time'] IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][variable] = {} IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][variable]['units'] = "meters" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][variable]['contentType'] = "referenceInformation" IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][variable]['long_name'] = long_name IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][variable]['description'] = description IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][variable]['source'] = TIDE_MODEL IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][variable]['reference'] = reference IS2_atl07_tide_attrs[gtx]['sea_ice_segments']['geophysical'][variable]['coordinates'] = \ "../height_segment_id ../delta_time ../latitude ../longitude" #-- output tidal HDF5 file args = (PRD,HEM,TIDE_MODEL,YY,MM,DD,HH,MN,SS,TRK,CYCL,SN,RL,VERS,AUX) ff = '{0}-{1}_{2}_TIDES_{3}{4}{5}{6}{7}{8}_{9}{10}{11}_{12}_{13}{14}.h5' #-- print file information print('\t{0}'.format(ff.format(*args))) if VERBOSE else None HDF5_ATL07_tide_write(IS2_atl07_tide, IS2_atl07_tide_attrs, CLOBBER=True, INPUT=os.path.basename(FILE), FILL_VALUE=IS2_atl07_fill, DIMENSIONS=IS2_atl07_dims, FILENAME=os.path.join(DIRECTORY,ff.format(*args))) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY,ff.format(*args)), MODE)
def compute_tides_ICESat(tide_dir, INPUT_FILE, TIDE_MODEL=None, METHOD='spline', EXTRAPOLATE=False, CUTOFF=None, VERBOSE=False, MODE=0o775): #-- select between tide models if (TIDE_MODEL == 'CATS0201'): grid_file = os.path.join(tide_dir, 'cats0201_tmd', 'grid_CATS') model_file = os.path.join(tide_dir, 'cats0201_tmd', 'h0_CATS02_01') reference = 'https://mail.esr.org/polar_tide_models/Model_CATS0201.html' variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'CATS2008'): grid_file = os.path.join(tide_dir, 'CATS2008', 'grid_CATS2008') model_file = os.path.join(tide_dir, 'CATS2008', 'hf.CATS2008.out') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = 'CATS2008' TYPE = 'z' elif (TIDE_MODEL == 'CATS2008_load'): grid_file = os.path.join(tide_dir, 'CATS2008a_SPOTL_Load', 'grid_CATS2008a_opt') model_file = os.path.join(tide_dir, 'CATS2008a_SPOTL_Load', 'h_CATS2008a_SPOTL_load') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') variable = 'd_ldElv' long_name = "Load Tide Elevation" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'OTIS' EPSG = 'CATS2008' TYPE = 'z' elif (TIDE_MODEL == 'TPXO9-atlas'): model_directory = os.path.join(tide_dir, 'TPXO9_atlas') grid_file = os.path.join(model_directory, 'grid_tpxo9_atlas.nc.gz') model_files = [ 'h_q1_tpxo9_atlas_30.nc.gz', 'h_o1_tpxo9_atlas_30.nc.gz', 'h_p1_tpxo9_atlas_30.nc.gz', 'h_k1_tpxo9_atlas_30.nc.gz', 'h_n2_tpxo9_atlas_30.nc.gz', 'h_m2_tpxo9_atlas_30.nc.gz', 'h_s2_tpxo9_atlas_30.nc.gz', 'h_k2_tpxo9_atlas_30.nc.gz', 'h_m4_tpxo9_atlas_30.nc.gz', 'h_ms4_tpxo9_atlas_30.nc.gz', 'h_mn4_tpxo9_atlas_30.nc.gz', 'h_2n2_tpxo9_atlas_30.nc.gz' ] model_file = [os.path.join(model_directory, m) for m in model_files] reference = 'http://volkov.oce.orst.edu/tides/tpxo9_atlas.html' variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'netcdf' TYPE = 'z' SCALE = 1.0 / 1000.0 GZIP = True elif (TIDE_MODEL == 'TPXO9-atlas-v2'): model_directory = os.path.join(tide_dir, 'TPXO9_atlas_v2') grid_file = os.path.join(model_directory, 'grid_tpxo9_atlas_30_v2.nc.gz') model_files = [ 'h_q1_tpxo9_atlas_30_v2.nc.gz', 'h_o1_tpxo9_atlas_30_v2.nc.gz', 'h_p1_tpxo9_atlas_30_v2.nc.gz', 'h_k1_tpxo9_atlas_30_v2.nc.gz', 'h_n2_tpxo9_atlas_30_v2.nc.gz', 'h_m2_tpxo9_atlas_30_v2.nc.gz', 'h_s2_tpxo9_atlas_30_v2.nc.gz', 'h_k2_tpxo9_atlas_30_v2.nc.gz', 'h_m4_tpxo9_atlas_30_v2.nc.gz', 'h_ms4_tpxo9_atlas_30_v2.nc.gz', 'h_mn4_tpxo9_atlas_30_v2.nc.gz', 'h_2n2_tpxo9_atlas_30_v2.nc.gz' ] model_file = [os.path.join(model_directory, m) for m in model_files] reference = 'https://www.tpxo.net/global/tpxo9-atlas' variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'netcdf' TYPE = 'z' SCALE = 1.0 / 1000.0 GZIP = True elif (TIDE_MODEL == 'TPXO9-atlas-v3'): model_directory = os.path.join(tide_dir, 'TPXO9_atlas_v3') grid_file = os.path.join(model_directory, 'grid_tpxo9_atlas_30_v3.nc.gz') model_files = [ 'h_q1_tpxo9_atlas_30_v3.nc.gz', 'h_o1_tpxo9_atlas_30_v3.nc.gz', 'h_p1_tpxo9_atlas_30_v3.nc.gz', 'h_k1_tpxo9_atlas_30_v3.nc.gz', 'h_n2_tpxo9_atlas_30_v3.nc.gz', 'h_m2_tpxo9_atlas_30_v3.nc.gz', 'h_s2_tpxo9_atlas_30_v3.nc.gz', 'h_k2_tpxo9_atlas_30_v3.nc.gz', 'h_m4_tpxo9_atlas_30_v3.nc.gz', 'h_ms4_tpxo9_atlas_30_v3.nc.gz', 'h_mn4_tpxo9_atlas_30_v3.nc.gz', 'h_2n2_tpxo9_atlas_30_v3.nc.gz', 'h_mf_tpxo9_atlas_30_v3.nc.gz', 'h_mm_tpxo9_atlas_30_v3.nc.gz' ] model_file = [os.path.join(model_directory, m) for m in model_files] reference = 'https://www.tpxo.net/global/tpxo9-atlas' variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'netcdf' TYPE = 'z' SCALE = 1.0 / 1000.0 GZIP = True elif (TIDE_MODEL == 'TPXO9-atlas-v4'): model_directory = os.path.join(tide_dir, 'TPXO9_atlas_v4') grid_file = os.path.join(model_directory, 'grid_tpxo9_atlas_30_v4') model_files = [ 'h_q1_tpxo9_atlas_30_v4', 'h_o1_tpxo9_atlas_30_v4', 'h_p1_tpxo9_atlas_30_v4', 'h_k1_tpxo9_atlas_30_v4', 'h_n2_tpxo9_atlas_30_v4', 'h_m2_tpxo9_atlas_30_v4', 'h_s2_tpxo9_atlas_30_v4', 'h_k2_tpxo9_atlas_30_v4', 'h_m4_tpxo9_atlas_30_v4', 'h_ms4_tpxo9_atlas_30_v4', 'h_mn4_tpxo9_atlas_30_v4', 'h_2n2_tpxo9_atlas_30_v4', 'h_mf_tpxo9_atlas_30_v4', 'h_mm_tpxo9_atlas_30_v4' ] model_file = [os.path.join(model_directory, m) for m in model_files] reference = 'https://www.tpxo.net/global/tpxo9-atlas' variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO9.1'): grid_file = os.path.join(tide_dir, 'TPXO9.1', 'DATA', 'grid_tpxo9') model_file = os.path.join(tide_dir, 'TPXO9.1', 'DATA', 'h_tpxo9.v1') reference = 'http://volkov.oce.orst.edu/tides/global.html' variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO8-atlas'): grid_file = os.path.join(tide_dir, 'tpxo8_atlas', 'grid_tpxo8atlas_30_v1') model_file = os.path.join(tide_dir, 'tpxo8_atlas', 'hf.tpxo8_atlas_30_v1') reference = 'http://volkov.oce.orst.edu/tides/tpxo8_atlas.html' variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'ATLAS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO7.2'): grid_file = os.path.join(tide_dir, 'TPXO7.2_tmd', 'grid_tpxo7.2') model_file = os.path.join(tide_dir, 'TPXO7.2_tmd', 'h_tpxo7.2') reference = 'http://volkov.oce.orst.edu/tides/global.html' variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'TPXO7.2_load'): grid_file = os.path.join(tide_dir, 'TPXO7.2_load', 'grid_tpxo6.2') model_file = os.path.join(tide_dir, 'TPXO7.2_load', 'h_tpxo7.2_load') reference = 'http://volkov.oce.orst.edu/tides/global.html' variable = 'd_ldElv' long_name = "Load Tide Elevation" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'OTIS' EPSG = '4326' TYPE = 'z' elif (TIDE_MODEL == 'AODTM-5'): grid_file = os.path.join(tide_dir, 'aodtm5_tmd', 'grid_Arc5km') model_file = os.path.join(tide_dir, 'aodtm5_tmd', 'h0_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aodtm-5/') variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'AOTIM-5'): grid_file = os.path.join(tide_dir, 'aotim5_tmd', 'grid_Arc5km') model_file = os.path.join(tide_dir, 'aotim5_tmd', 'h_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'AOTIM-5-2018'): grid_file = os.path.join(tide_dir, 'Arc5km2018', 'grid_Arc5km2018') model_file = os.path.join(tide_dir, 'Arc5km2018', 'h_Arc5km2018') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = 'PSNorth' TYPE = 'z' elif (TIDE_MODEL == 'Gr1km-v2'): grid_file = os.path.join(tide_dir, 'greenlandTMD_v2', 'grid_Greenland8.v2') model_file = os.path.join(tide_dir, 'greenlandTMD_v2', 'h_Greenland8.v2') reference = 'https://doi.org/10.1002/2016RG000546' variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'OTIS' EPSG = '3413' TYPE = 'z' elif (TIDE_MODEL == 'GOT4.7'): model_directory = os.path.join(tide_dir, 'GOT4.7', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] model_file = [os.path.join(model_directory, m) for m in model_files] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'GOT' SCALE = 1.0 / 100.0 GZIP = True elif (TIDE_MODEL == 'GOT4.7_load'): model_directory = os.path.join(tide_dir, 'GOT4.7', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] model_file = [os.path.join(model_directory, m) for m in model_files] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'd_ldElv' long_name = "Load Tide Elevation" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'GOT' SCALE = 1.0 / 1000.0 GZIP = True elif (TIDE_MODEL == 'GOT4.8'): model_directory = os.path.join(tide_dir, 'got4.8', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] model_file = [os.path.join(model_directory, m) for m in model_files] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'GOT' SCALE = 1.0 / 100.0 GZIP = True elif (TIDE_MODEL == 'GOT4.8_load'): model_directory = os.path.join(tide_dir, 'got4.8', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] model_file = [os.path.join(model_directory, m) for m in model_files] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'd_ldElv' long_name = "Load Tide Elevation" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'GOT' SCALE = 1.0 / 1000.0 GZIP = True elif (TIDE_MODEL == 'GOT4.10'): model_directory = os.path.join(tide_dir, 'GOT4.10c', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] model_file = [os.path.join(model_directory, m) for m in model_files] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'GOT' SCALE = 1.0 / 100.0 GZIP = True elif (TIDE_MODEL == 'GOT4.10_load'): model_directory = os.path.join(tide_dir, 'GOT4.10c', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] model_file = [os.path.join(model_directory, m) for m in model_files] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') variable = 'd_ldElv' long_name = "Load Tide Elevation" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'GOT' SCALE = 1.0 / 1000.0 GZIP = True elif (TIDE_MODEL == 'FES2014'): model_directory = os.path.join(tide_dir, 'fes2014', 'ocean_tide') model_files = [ '2n2.nc.gz', 'eps2.nc.gz', 'j1.nc.gz', 'k1.nc.gz', 'k2.nc.gz', 'l2.nc.gz', 'la2.nc.gz', 'm2.nc.gz', 'm3.nc.gz', 'm4.nc.gz', 'm6.nc.gz', 'm8.nc.gz', 'mf.nc.gz', 'mks2.nc.gz', 'mm.nc.gz', 'mn4.nc.gz', 'ms4.nc.gz', 'msf.nc.gz', 'msqm.nc.gz', 'mtm.nc.gz', 'mu2.nc.gz', 'n2.nc.gz', 'n4.nc.gz', 'nu2.nc.gz', 'o1.nc.gz', 'p1.nc.gz', 'q1.nc.gz', 'r2.nc.gz', 's1.nc.gz', 's2.nc.gz', 's4.nc.gz', 'sa.nc.gz', 'ssa.nc.gz', 't2.nc.gz' ] model_file = [os.path.join(model_directory, m) for m in model_files] c = [ '2n2', 'eps2', 'j1', 'k1', 'k2', 'l2', 'lambda2', 'm2', 'm3', 'm4', 'm6', 'm8', 'mf', 'mks2', 'mm', 'mn4', 'ms4', 'msf', 'msqm', 'mtm', 'mu2', 'n2', 'n4', 'nu2', 'o1', 'p1', 'q1', 'r2', 's1', 's2', 's4', 'sa', 'ssa', 't2' ] reference = ('https://www.aviso.altimetry.fr/en/data/products' 'auxiliary-products/global-tide-fes.html') variable = 'd_ocElv' long_name = "Ocean Tide Elevation" description = ( "Ocean Tides including diurnal and semi-diurnal " "(harmonic analysis), and longer period tides (dynamic and " "self-consistent equilibrium).") model_format = 'FES' TYPE = 'z' SCALE = 1.0 / 100.0 GZIP = True elif (TIDE_MODEL == 'FES2014_load'): model_directory = os.path.join(tide_dir, 'fes2014', 'load_tide') model_files = [ '2n2.nc.gz', 'eps2.nc.gz', 'j1.nc.gz', 'k1.nc.gz', 'k2.nc.gz', 'l2.nc.gz', 'la2.nc.gz', 'm2.nc.gz', 'm3.nc.gz', 'm4.nc.gz', 'm6.nc.gz', 'm8.nc.gz', 'mf.nc.gz', 'mks2.nc.gz', 'mm.nc.gz', 'mn4.nc.gz', 'ms4.nc.gz', 'msf.nc.gz', 'msqm.nc.gz', 'mtm.nc.gz', 'mu2.nc.gz', 'n2.nc.gz', 'n4.nc.gz', 'nu2.nc.gz', 'o1.nc.gz', 'p1.nc.gz', 'q1.nc.gz', 'r2.nc.gz', 's1.nc.gz', 's2.nc.gz', 's4.nc.gz', 'sa.nc.gz', 'ssa.nc.gz', 't2.nc.gz' ] model_file = [os.path.join(model_directory, m) for m in model_files] c = [ '2n2', 'eps2', 'j1', 'k1', 'k2', 'l2', 'lambda2', 'm2', 'm3', 'm4', 'm6', 'm8', 'mf', 'mks2', 'mm', 'mn4', 'ms4', 'msf', 'msqm', 'mtm', 'mu2', 'n2', 'n4', 'nu2', 'o1', 'p1', 'q1', 'r2', 's1', 's2', 's4', 'sa', 'ssa', 't2' ] reference = ('https://www.aviso.altimetry.fr/en/data/products' 'auxiliary-products/global-tide-fes.html') variable = 'd_ldElv' long_name = "Load Tide Elevation" description = "Local displacement due to Ocean Loading (-6 to 0 cm)" model_format = 'FES' TYPE = 'z' SCALE = 1.0 / 100.0 GZIP = True #-- get directory from INPUT_FILE print('{0} -->'.format(os.path.basename(INPUT_FILE))) if VERBOSE else None DIRECTORY = os.path.dirname(INPUT_FILE) #-- compile regular expression operator for extracting information from file rx = re.compile((r'GLAH(\d{2})_(\d{3})_(\d{1})(\d{1})(\d{2})_(\d{3})_' r'(\d{4})_(\d{1})_(\d{2})_(\d{4})\.H5'), re.VERBOSE) #-- extract parameters from ICESat/GLAS HDF5 file name #-- PRD: Product number (01, 05, 06, 12, 13, 14, or 15) #-- RL: Release number for process that created the product = 634 #-- RGTP: Repeat ground-track phase (1=8-day, 2=91-day, 3=transfer orbit) #-- ORB: Reference orbit number (starts at 1 and increments each time a #-- new reference orbit ground track file is obtained.) #-- INST: Instance number (increments every time the satellite enters a #-- different reference orbit) #-- CYCL: Cycle of reference orbit for this phase #-- TRK: Track within reference orbit #-- SEG: Segment of orbit #-- GRAN: Granule version number #-- TYPE: File type try: PRD, RL, RGTP, ORB, INST, CYCL, TRK, SEG, GRAN, TYPE = rx.findall( INPUT_FILE).pop() except: #-- output tide HDF5 file (generic) fileBasename, fileExtension = os.path.splitext(INPUT_FILE) args = (fileBasename, TIDE_MODEL, fileExtension) OUTPUT_FILE = '{0}_{1}_TIDES{2}'.format(*args) else: #-- output tide HDF5 file for NSIDC granules args = (PRD, RL, TIDE_MODEL, RGTP, ORB, INST, CYCL, TRK, SEG, GRAN, TYPE) file_format = 'GLAH{0}_{1}_{2}_TIDES_{3}{4}{5}_{6}_{7}_{8}_{9}_{10}.h5' OUTPUT_FILE = file_format.format(*args) #-- read GLAH12 HDF5 file fileID = h5py.File(INPUT_FILE, 'r') n_40HZ, = fileID['Data_40HZ']['Time']['i_rec_ndx'].shape #-- get variables and attributes rec_ndx_40HZ = fileID['Data_40HZ']['Time']['i_rec_ndx'][:].copy() #-- seconds since 2000-01-01 12:00:00 UTC (J2000) DS_UTCTime_40HZ = fileID['Data_40HZ']['DS_UTCTime_40'][:].copy() #-- Latitude (degrees North) lat_TPX = fileID['Data_40HZ']['Geolocation']['d_lat'][:].copy() #-- Longitude (degrees East) lon_40HZ = fileID['Data_40HZ']['Geolocation']['d_lon'][:].copy() #-- Elevation (height above TOPEX/Poseidon ellipsoid in meters) elev_TPX = fileID['Data_40HZ']['Elevation_Surfaces']['d_elev'][:].copy() fv = fileID['Data_40HZ']['Elevation_Surfaces']['d_elev'].attrs[ '_FillValue'] #-- semimajor axis (a) and flattening (f) for TP and WGS84 ellipsoids atop, ftop = (6378136.3, 1.0 / 298.257) awgs, fwgs = (6378137.0, 1.0 / 298.257223563) #-- convert from Topex/Poseidon to WGS84 Ellipsoids lat_40HZ, elev_40HZ = pyTMD.spatial.convert_ellipsoid(lat_TPX, elev_TPX, atop, ftop, awgs, fwgs, eps=1e-12, itmax=10) #-- convert time from J2000 to days relative to Jan 1, 1992 (48622mjd) #-- J2000: seconds since 2000-01-01 12:00:00 UTC tide_time = pyTMD.time.convert_delta_time(DS_UTCTime_40HZ, epoch1=(2000, 1, 1, 12, 0, 0), epoch2=(1992, 1, 1, 0, 0, 0), scale=1.0 / 86400.0) #-- delta time (TT - UT1) file delta_file = pyTMD.utilities.get_data_path(['data', 'merged_deltat.data']) #-- read tidal constants and interpolate to grid points if model_format in ('OTIS', 'ATLAS'): amp, ph, D, c = extract_tidal_constants(lon_40HZ, lat_40HZ, grid_file, model_file, EPSG, TYPE=TYPE, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, GRID=model_format) deltat = np.zeros_like(tide_time) elif (model_format == 'netcdf'): amp, ph, D, c = extract_netcdf_constants(lon_40HZ, lat_40HZ, grid_file, model_file, TYPE=TYPE, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=SCALE, GZIP=GZIP) deltat = np.zeros_like(tide_time) elif (model_format == 'GOT'): amp, ph, c = extract_GOT_constants(lon_40HZ, lat_40HZ, model_file, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=SCALE, GZIP=GZIP) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, tide_time) elif (model_format == 'FES'): amp, ph = extract_FES_constants(lon_40HZ, lat_40HZ, model_file, TYPE=TYPE, VERSION=TIDE_MODEL, METHOD=METHOD, EXTRAPOLATE=EXTRAPOLATE, CUTOFF=CUTOFF, SCALE=SCALE, GZIP=GZIP) #-- interpolate delta times from calendar dates to tide time deltat = calc_delta_time(delta_file, tide_time) #-- calculate complex phase in radians for Euler's cph = -1j * ph * np.pi / 180.0 #-- calculate constituent oscillation hc = amp * np.exp(cph) #-- predict tidal elevations at time and infer minor corrections tide = np.ma.empty((n_40HZ), fill_value=fv) tide.mask = np.any(hc.mask, axis=1) tide.data[:] = predict_tide_drift(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model_format) minor = infer_minor_corrections(tide_time, hc, c, DELTAT=deltat, CORRECTIONS=model_format) tide.data[:] += minor.data[:] #-- replace masked and nan values with fill value invalid, = np.nonzero(np.isnan(tide.data) | tide.mask) tide.data[invalid] = tide.fill_value tide.mask[invalid] = True #-- copy variables for outputting to HDF5 file IS_gla12_tide = dict(Data_40HZ={}) IS_gla12_fill = dict(Data_40HZ={}) IS_gla12_tide_attrs = dict(Data_40HZ={}) #-- copy global file attributes global_attribute_list = [ 'featureType', 'title', 'comment', 'summary', 'license', 'references', 'AccessConstraints', 'CitationforExternalPublication', 'contributor_role', 'contributor_name', 'creator_name', 'creator_email', 'publisher_name', 'publisher_email', 'publisher_url', 'platform', 'instrument', 'processing_level', 'date_created', 'spatial_coverage_type', 'history', 'keywords', 'keywords_vocabulary', 'naming_authority', 'project', 'time_type', 'date_type', 'time_coverage_start', 'time_coverage_end', 'time_coverage_duration', 'source', 'HDFVersion', 'identifier_product_type', 'identifier_product_format_version', 'Conventions', 'institution', 'ReprocessingPlanned', 'ReprocessingActual', 'LocalGranuleID', 'ProductionDateTime', 'LocalVersionID', 'PGEVersion', 'OrbitNumber', 'StartOrbitNumber', 'StopOrbitNumber', 'EquatorCrossingLongitude', 'EquatorCrossingTime', 'EquatorCrossingDate', 'ShortName', 'VersionID', 'InputPointer', 'RangeBeginningTime', 'RangeEndingTime', 'RangeBeginningDate', 'RangeEndingDate', 'PercentGroundHit', 'OrbitQuality', 'Cycle', 'Track', 'Instrument_State', 'Timing_Bias', 'ReferenceOrbit', 'SP_ICE_PATH_NO', 'SP_ICE_GLAS_StartBlock', 'SP_ICE_GLAS_EndBlock', 'Instance', 'Range_Bias', 'Instrument_State_Date', 'Instrument_State_Time', 'Range_Bias_Date', 'Range_Bias_Time', 'Timing_Bias_Date', 'Timing_Bias_Time', 'identifier_product_doi', 'identifier_file_uuid', 'identifier_product_doi_authority' ] for att in global_attribute_list: IS_gla12_tide_attrs[att] = fileID.attrs[att] #-- add attributes for input GLA12 file IS_gla12_tide_attrs['input_files'] = os.path.basename(INPUT_FILE) #-- update geospatial ranges for ellipsoid IS_gla12_tide_attrs['geospatial_lat_min'] = np.min(lat_40HZ) IS_gla12_tide_attrs['geospatial_lat_max'] = np.max(lat_40HZ) IS_gla12_tide_attrs['geospatial_lon_min'] = np.min(lon_40HZ) IS_gla12_tide_attrs['geospatial_lon_max'] = np.max(lon_40HZ) IS_gla12_tide_attrs['geospatial_lat_units'] = "degrees_north" IS_gla12_tide_attrs['geospatial_lon_units'] = "degrees_east" IS_gla12_tide_attrs['geospatial_ellipsoid'] = "WGS84" #-- copy 40Hz group attributes for att_name, att_val in fileID['Data_40HZ'].attrs.items(): IS_gla12_tide_attrs['Data_40HZ'][att_name] = att_val #-- copy attributes for time, geolocation and geophysical groups for var in ['Time', 'Geolocation', 'Geophysical']: IS_gla12_tide['Data_40HZ'][var] = {} IS_gla12_fill['Data_40HZ'][var] = {} IS_gla12_tide_attrs['Data_40HZ'][var] = {} for att_name, att_val in fileID['Data_40HZ'][var].attrs.items(): IS_gla12_tide_attrs['Data_40HZ'][var][att_name] = att_val #-- J2000 time IS_gla12_tide['Data_40HZ']['DS_UTCTime_40'] = DS_UTCTime_40HZ IS_gla12_fill['Data_40HZ']['DS_UTCTime_40'] = None IS_gla12_tide_attrs['Data_40HZ']['DS_UTCTime_40'] = {} for att_name, att_val in fileID['Data_40HZ']['DS_UTCTime_40'].attrs.items( ): if att_name not in ('DIMENSION_LIST', 'CLASS', 'NAME'): IS_gla12_tide_attrs['Data_40HZ']['DS_UTCTime_40'][ att_name] = att_val #-- record IS_gla12_tide['Data_40HZ']['Time']['i_rec_ndx'] = rec_ndx_40HZ IS_gla12_fill['Data_40HZ']['Time']['i_rec_ndx'] = None IS_gla12_tide_attrs['Data_40HZ']['Time']['i_rec_ndx'] = {} IS_gla12_tide_attrs['Data_40HZ']['Time']['i_rec_ndx']['coordinates'] = \ "../DS_UTCTime_40" for att_name, att_val in fileID['Data_40HZ']['Time'][ 'i_rec_ndx'].attrs.items(): if att_name not in ('DIMENSION_LIST', 'CLASS', 'NAME'): IS_gla12_tide_attrs['Data_40HZ']['Time']['i_rec_ndx'][ att_name] = att_val #-- latitude IS_gla12_tide['Data_40HZ']['Geolocation']['d_lat'] = lat_40HZ IS_gla12_fill['Data_40HZ']['Geolocation']['d_lat'] = None IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lat'] = {} IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lat']['coordinates'] = \ "../DS_UTCTime_40" for att_name, att_val in fileID['Data_40HZ']['Geolocation'][ 'd_lat'].attrs.items(): if att_name not in ('DIMENSION_LIST', 'CLASS', 'NAME'): IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lat'][ att_name] = att_val #-- longitude IS_gla12_tide['Data_40HZ']['Geolocation']['d_lon'] = lon_40HZ IS_gla12_fill['Data_40HZ']['Geolocation']['d_lon'] = None IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lon'] = {} IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lon']['coordinates'] = \ "../DS_UTCTime_40" for att_name, att_val in fileID['Data_40HZ']['Geolocation'][ 'd_lon'].attrs.items(): if att_name not in ('DIMENSION_LIST', 'CLASS', 'NAME'): IS_gla12_tide_attrs['Data_40HZ']['Geolocation']['d_lon'][ att_name] = att_val #-- geophysical variables #-- computed tide IS_gla12_tide['Data_40HZ']['Geophysical'][variable] = tide IS_gla12_fill['Data_40HZ']['Geophysical'][variable] = tide.fill_value IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][variable] = {} IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][variable][ 'units'] = "meters" IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][variable][ 'long_name'] = long_name IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][variable][ 'description'] = description IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][variable][ 'source'] = TIDE_MODEL IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][variable][ 'reference'] = reference IS_gla12_tide_attrs['Data_40HZ']['Geophysical'][variable]['coordinates'] = \ "../DS_UTCTime_40" #-- close the input HDF5 file fileID.close() #-- print file information print('\t{0}'.format(OUTPUT_FILE)) if VERBOSE else None HDF5_GLA12_tide_write(IS_gla12_tide, IS_gla12_tide_attrs, FILENAME=os.path.join(DIRECTORY, OUTPUT_FILE), FILL_VALUE=IS_gla12_fill, CLOBBER=True) #-- change the permissions mode os.chmod(os.path.join(DIRECTORY, OUTPUT_FILE), MODE)
def plot_tide_forecasts(tide_dir, LON, LAT, DATE, TIDE_MODEL=''): #-- select between tide models if (TIDE_MODEL == 'CATS0201'): grid_file = os.path.join(tide_dir, 'cats0201_tmd', 'grid_CATS') model_file = os.path.join(tide_dir, 'cats0201_tmd', 'h0_CATS02_01') reference = 'https://mail.esr.org/polar_tide_models/Model_CATS0201.html' model_format = 'OTIS' EPSG = '4326' type = 'z' elif (TIDE_MODEL == 'CATS2008'): grid_file = os.path.join(tide_dir, 'CATS2008', 'grid_CATS2008a_opt') model_file = os.path.join(tide_dir, 'CATS2008', 'hf.CATS2008.out') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') model_format = 'OTIS' EPSG = 'CATS2008' type = 'z' elif (TIDE_MODEL == 'CATS2008_load'): grid_file = os.path.join(tide_dir, 'CATS2008a_SPOTL_Load', 'grid_CATS2008a_opt') model_file = os.path.join(tide_dir, 'CATS2008a_SPOTL_Load', 'h_CATS2008a_SPOTL_load') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/cats2008/') model_format = 'OTIS' EPSG = 'CATS2008' type = 'z' elif (TIDE_MODEL == 'TPXO9-atlas'): model_directory = os.path.join(tide_dir, 'TPXO9_atlas') grid_file = 'grid_tpxo9_atlas.nc.gz' model_files = [ 'h_q1_tpxo9_atlas_30.nc.gz', 'h_o1_tpxo9_atlas_30.nc.gz', 'h_p1_tpxo9_atlas_30.nc.gz', 'h_k1_tpxo9_atlas_30.nc.gz', 'h_n2_tpxo9_atlas_30.nc.gz', 'h_m2_tpxo9_atlas_30.nc.gz', 'h_s2_tpxo9_atlas_30.nc.gz', 'h_k2_tpxo9_atlas_30.nc.gz', 'h_m4_tpxo9_atlas_30.nc.gz', 'h_ms4_tpxo9_atlas_30.nc.gz', 'h_mn4_tpxo9_atlas_30.nc.gz', 'h_2n2_tpxo9_atlas_30.nc.gz' ] reference = 'http://volkov.oce.orst.edu/tides/tpxo9_atlas.html' model_format = 'netcdf' type = 'z' SCALE = 1.0 / 1000.0 elif (TIDE_MODEL == 'TPXO9.1'): grid_file = os.path.join(tide_dir, 'TPXO9.1', 'DATA', 'grid_tpxo9') model_file = os.path.join(tide_dir, 'TPXO9.1', 'DATA', 'h_tpxo9.v1') reference = 'http://volkov.oce.orst.edu/tides/global.html' model_format = 'OTIS' EPSG = '4326' type = 'z' elif (TIDE_MODEL == 'TPXO8-atlas'): grid_file = os.path.join(tide_dir, 'tpxo8_atlas', 'grid_tpxo8atlas_30_v1') model_file = os.path.join(tide_dir, 'tpxo8_atlas', 'hf.tpxo8_atlas_30_v1') reference = 'http://volkov.oce.orst.edu/tides/tpxo8_atlas.html' model_format = 'ATLAS' EPSG = '4326' type = 'z' elif (TIDE_MODEL == 'TPXO7.2'): grid_file = os.path.join(tide_dir, 'TPXO7.2_tmd', 'grid_tpxo7.2') model_file = os.path.join(tide_dir, 'TPXO7.2_tmd', 'h_tpxo7.2') reference = 'http://volkov.oce.orst.edu/tides/global.html' model_format = 'OTIS' EPSG = '4326' type = 'z' elif (TIDE_MODEL == 'TPXO7.2_load'): grid_file = os.path.join(tide_dir, 'TPXO7.2_load', 'grid_tpxo6.2') model_file = os.path.join(tide_dir, 'TPXO7.2_load', 'h_tpxo7.2_load') reference = 'http://volkov.oce.orst.edu/tides/global.html' model_format = 'OTIS' EPSG = '4326' type = 'z' elif (TIDE_MODEL == 'AODTM-5'): grid_file = os.path.join(tide_dir, 'aodtm5_tmd', 'grid_Arc5km') model_file = os.path.join(tide_dir, 'aodtm5_tmd', 'h0_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aodtm-5/') model_format = 'OTIS' EPSG = '3996' type = 'z' elif (TIDE_MODEL == 'AOTIM-5'): grid_file = os.path.join(tide_dir, 'aotim5_tmd', 'grid_Arc5km') model_file = os.path.join(tide_dir, 'aotim5_tmd', 'h_Arc5km.oce') reference = ('https://www.esr.org/research/polar-tide-models/' 'list-of-polar-tide-models/aotim-5/') model_format = 'OTIS' EPSG = '3996' type = 'z' elif (TIDE_MODEL == 'GOT4.7'): model_directory = os.path.join(tide_dir, 'GOT4.7', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') model_format = 'GOT' SCALE = 1.0 / 100.0 elif (TIDE_MODEL == 'GOT4.7_load'): model_directory = os.path.join(tide_dir, 'GOT4.7', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') model_format = 'GOT' SCALE = 1.0 / 1000.0 elif (TIDE_MODEL == 'GOT4.8'): model_directory = os.path.join(tide_dir, 'got4.8', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') model_format = 'GOT' SCALE = 1.0 / 100.0 elif (TIDE_MODEL == 'GOT4.8_load'): model_directory = os.path.join(tide_dir, 'got4.8', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') model_format = 'GOT' SCALE = 1.0 / 1000.0 elif (TIDE_MODEL == 'GOT4.10'): model_directory = os.path.join(tide_dir, 'GOT4.10c', 'grids_oceantide') model_files = [ 'q1.d.gz', 'o1.d.gz', 'p1.d.gz', 'k1.d.gz', 'n2.d.gz', 'm2.d.gz', 's2.d.gz', 'k2.d.gz', 's1.d.gz', 'm4.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') model_format = 'GOT' SCALE = 1.0 / 100.0 elif (TIDE_MODEL == 'GOT4.10_load'): model_directory = os.path.join(tide_dir, 'GOT4.10c', 'grids_loadtide') model_files = [ 'q1load.d.gz', 'o1load.d.gz', 'p1load.d.gz', 'k1load.d.gz', 'n2load.d.gz', 'm2load.d.gz', 's2load.d.gz', 'k2load.d.gz', 's1load.d.gz', 'm4load.d.gz' ] c = ['q1', 'o1', 'p1', 'k1', 'n2', 'm2', 's2', 'k2', 's1', 'm4'] reference = ('https://denali.gsfc.nasa.gov/personal_pages/ray/' 'MiscPubs/19990089548_1999150788.pdf') model_format = 'GOT' SCALE = 1.0 / 1000.0 #-- calculate the modified Julian day from the calendar date MJD = calc_modified_julian_day(DATE.tm_year, DATE.tm_mon, DATE.tm_mday) TIME = np.arange(7 * 1440) / 1440.0 #-- read tidal constants and interpolate to grid points if model_format in ('OTIS', 'ATLAS'): amp, ph, D, c = extract_tidal_constants(np.array([LON]), np.array([LAT]), grid_file, model_file, EPSG, type, METHOD='spline', GRID=model_format) deltat = np.zeros_like(MJD) elif (model_format == 'netcdf'): amp, ph, D, c = extract_netcdf_constants(np.array([LON]), np.array([LAT]), model_directory, grid_file, model_files, type, METHOD='spline', SCALE=SCALE) deltat = np.zeros_like(MJD) elif (model_format == 'GOT'): amp, ph = extract_GOT_constants(np.array([LON]), np.array([LAT]), model_directory, model_files, METHOD='spline', SCALE=SCALE) delta_file = os.path.join(tide_dir, 'deltat.data') deltat = calc_delta_time(delta_file, MJD + TIME) #-- convert phase to radians cph = -1j * ph * np.pi / 180.0 hc = amp * np.exp(cph) #-- convert time from MJD to days relative to Jan 1, 1992 (48622 MJD) #-- predict tidal elevations at time 1 and infer minor corrections TIDE = predict_tidal_ts(MJD + TIME - 48622.0, hc, c, DELTAT=deltat, CORRECTIONS=model_format) TIDE += infer_minor_corrections(MJD + TIME - 48622.0, hc, c, DELTAT=deltat, CORRECTIONS=model_format) #-- convert to centimeters TIDE *= 100.0 #-- differentiate to calculate high and low tides diff = np.zeros_like(TIME, dtype=np.float) #-- forward differentiation for starting point diff[0] = TIDE[1] - TIDE[0] #-- backward differentiation for end point diff[-1] = TIDE[-1] - TIDE[-2] #-- centered differentiation for all others diff[1:-1] = (TIDE[2:] - TIDE[0:-2]) / 2.0 #-- indices of high and low tides htindex, = np.nonzero((np.sign(diff[0:-1]) >= 0) & (np.sign(diff[1:]) < 0)) ltindex, = np.nonzero((np.sign(diff[0:-1]) <= 0) & (np.sign(diff[1:]) > 0)) #-- create plot with tidal displacements, high and low tides and dates fig, ax1 = plt.subplots(num=1) ax1.plot(TIME * 24.0, TIDE, 'k') ax1.plot(TIME[htindex] * 24.0, TIDE[htindex], 'r*') ax1.plot(TIME[ltindex] * 24.0, TIDE[ltindex], 'b*') for h in range(24, 192, 24): ax1.axvline(h, color='gray', lw=0.5, ls='dashed', dashes=(11, 5)) ax1.set_xlim(0, 7 * 24) ax1.set_ylabel('{0} Tidal Displacement [cm]'.format(TIDE_MODEL)) args = (DATE.tm_year, DATE.tm_mon, DATE.tm_mday) ax1.set_xlabel( 'Time from {0:4d}-{1:02d}-{2:02d} UTC [Hours]'.format(*args)) ax1.set_title(u'{0:0.6f}\u00b0N {1:0.6f}\u00b0W'.format(LAT, LON)) fig.subplots_adjust(left=0.10, right=0.98, bottom=0.10, top=0.95) plt.show()