Source code for pysatMadrigal.instruments.methods.gnss

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Full license can be found in License.md
# Full author list can be found in .zenodo.json file
# DOI:10.5281/zenodo.3824979
#
# DISTRIBUTION STATEMENT A: Approved for public release. Distribution is
# unlimited.
# ----------------------------------------------------------------------------
"""Methods supporting the Global Navigation Satellite System platform."""

import datetime as dt
import h5py
import numpy as np
import pandas as pds

import pysat

from pysatMadrigal.instruments.methods import general


[docs] def acknowledgements(name): """Provide the acknowledgements for different GNSS instruments. Parameters ---------- name : str Instrument name Returns ------- ackn : str Acknowledgement information to provide in studies using this data """ ackn = {'tec': ''.join(["GPS TEC data products and access through the ", "Madrigal distributed data system are provided to ", "the community by the Massachusetts Institute of ", "Technology under support from U.S. National ", "Science Foundation grant AGS-1242204. Data for ", "the TEC processing is provided by the following ", "organizations: UNAVCO, Scripps Orbit and ", "Permanent Array Center, Institut Geographique ", "National, France, International GNSS Service, The", " Crustal Dynamics Data Information System ", "(CDDIS), National Geodetic Survey, Instituto ", "Brasileiro de Geografiae Estatística, RAMSAC ", "CORS of Instituto Geográfico Nacional del la ", "República Agentina, Arecibo Observatory, ", "Low-Latitude Ionospheric Sensor Network (LISN), ", "Topcon Positioning Systems, Inc., Canadian High ", "Arctic Ionospheric Network, Institute of Geology", " and Geophysics, Chinese Academy of Sciences, ", "China Meterorology Administration, Centro di ", "Niveau des Eaux Littorales Ricerche Sismogiche, ", "Système d’Observation du (SONEL), RENAG : ", "REseau NAtional GPS permanent, and GeoNet—the ", "official source of geological hazard information ", "for New Zealand."])} return ackn[name]
[docs] def references(name): """Provide suggested references for the specified data set. Parameters ---------- name : str Instrument name Returns ------- refs : str Suggested Instrument reference(s) """ refs = {'tec': "\n".join([ "Rideout and Coster (2006) doi:10.1007/s10291-006-0029-5", "Vierinen et al., (2016) doi:10.5194/amt-9-1303-2016"])} return refs[name]
[docs] def load_vtec(fnames): """Load the GNSS vertical TEC data. Parameters ---------- fnames : list List of filenames Returns ------- data : xarray.Dataset Object containing satellite data meta : pysat.Meta Object containing metadata such as column names and units lat_key : list Latitude key names lon_key : list Longitude key names """ # Define the xarray coordinate dimensions and lat/lon keys xcoords = {('time', 'gdlat', 'glon', 'kindat', 'kinst'): ['gdalt', 'tec', 'dtec'], ('time', ): ['year', 'month', 'day', 'hour', 'min', 'sec', 'ut1_unix', 'ut2_unix', 'recno']} lat_keys = ['gdlat'] lon_keys = ['glon'] # Load the specified data data, meta = general.load(fnames, 'vtec', '', xarray_coords=xcoords) # Fix the units for tec and dtec meta['tec'] = {meta.labels.units: 'TECU', meta.labels.min_val: 0.0, meta.labels.max_val: np.nan} meta['dtec'] = {meta.labels.units: 'TECU', meta.labels.min_val: 0.0, meta.labels.max_val: np.nan} # Get the maximum and minimum values for altiutde, along with lat/lon keys meta['gdalt'] = {meta.labels.min_val: 0.0, meta.labels.max_val: np.nan} return data, meta, lat_keys, lon_keys
[docs] def load_site(fnames): """Load the GNSS TEC site data. Parameters ---------- fnames : list List of filenames Returns ------- data : xarray.Dataset Object containing satellite data meta : pysat.Meta Object containing metadata such as column names and units lat_keys : list Latitude key names lon_keys : list Longitude key names """ # Define the xarray coordinate dimensions and lat/lon keys xcoords = {('time', 'gps_site'): ['gdlatr', 'gdlonr']} lat_keys = ['gdlatr'] lon_keys = ['gdlonr'] # Load the specified data data, meta = general.load(fnames, 'site', '', xarray_coords=xcoords) return data, meta, lat_keys, lon_keys
[docs] def load_los(fnames, los_method, los_value, gnss_network='all'): """Load the GNSS slant TEC data. Parameters ---------- fnames : list List of filenames los_method : str For 'los' tag only, load data for a unique GNSS receiver site ('site') or at a unique time ('time') los_value : str or dt.datetime For 'los' tag only, load data at this unique site or time gnss_network : bool Limit data by GNSS network, if not 'all'. Currently supports 'all', 'gps', and 'glonass' (default='all') Returns ------- data : xarray.Dataset Object containing satellite data meta : pysat.Meta Object containing metadata such as column names and units lat_keys : list Latitude key names lon_keys : list Longitude key names """ # Define the xarray coordinate dimensions and lat/lon keys xcoords = {('time', 'gps_site', 'sat_id', 'kindat', 'kinst'): ['pierce_alt', 'los_tec', 'dlos_tec', 'tec', 'azm', 'elm', 'gdlat', 'glon', 'rec_bias', 'drec_bias'], ('time', ): ['year', 'month', 'day', 'hour', 'min', 'sec', 'ut1_unix', 'ut2_unix', 'recno'], ('time', 'sat_id', ): ['gnss_type'], ('time', 'gps_site', ): ['gdlatr', 'gdlonr']} lat_keys = ['gdlatr', 'gdlat'] lon_keys = ['gdlonr', 'glon'] # Sort and test the desired filenames by file format load_file_types = general.sort_file_formats(fnames) for ftype in load_file_types.keys(): if ftype != 'hdf5' and len(load_file_types[ftype]) > 0: pysat.logger.warning( 'unable to load non-HDF5 slant TEC files: {:}'.format( load_file_types[ftype])) # Initalize the meta data meta = pysat.Meta() # Load the data using the desired method if los_method.lower() == 'site': sel_key = 'gps_site' # Convert the site to bytes los_value = np.bytes_(los_value) elif los_method.lower() == 'time': sel_key = 'ut1_unix' # Convert the input datetime to UNIX seconds los_value = (los_value - dt.datetime(1970, 1, 1)).total_seconds() else: raise ValueError('unsupported selection type: {:}'.format(los_method)) # Load the data by desired method data = list() labels = list() for fname in load_file_types['hdf5']: with h5py.File(fname, 'r') as fin: sel_arr = fin['Data']['Table Layout'][sel_key] sel_mask = sel_arr == los_value if gnss_network.lower() != 'all': # Redefine the selection mask to include network as well gnss_val = '{:8s}'.format(gnss_network.upper()) try: net_arr = fin['Data']['Table Layout']['gnss_type'][sel_mask] sel_mask[sel_mask] = net_arr.astype(str) == gnss_val except ValueError: # If the 'gnss_type' is not available, all data is GPS if gnss_network.lower() != 'gps': sel_mask[sel_mask] = False # Save the output for the desired slice if sel_mask.any(): data.extend(list(fin['Data']['Table Layout'][sel_mask])) # Save the meta data labels = general.update_meta_with_hdf5(fin, meta) # If this is time selection, only need to load from one file if len(data) > 0: break # Load data into frame, with labels from metadata data = pds.DataFrame.from_records(data, columns=labels) if not data.empty: # Enforce lowercase variable names data.columns = [item.lower() for item in data.columns] # Convert the data to an xarray Dataset time_ind = general.build_madrigal_datetime_index(data) else: time_ind = None # Convert the output to xarray data = general.convert_pandas_to_xarray(xcoords, data, time_ind) return data, meta, lat_keys, lon_keys
[docs] def get_los_receiver_sites(los_fnames): """Retrieve an array of unique receiver names for the desired LoS files. Parameters ---------- los_fnames : list List of filenames Returns ------- sites : np.array Array of strings containing GNSS receiver names with data in the files """ los_fnames = pysat.utils.listify(los_fnames) sites = list() # Get all of the potential sites for fname in los_fnames: with h5py.File(fname, 'r') as fin: site_arr = fin['Data']['Table Layout']['gps_site'] sites.extend(list(site_arr.astype(str))) # Find the unique sites sites = np.unique(sites) return sites
[docs] def get_los_times(los_fnames): """Retrieve an array of unique times for the desired LoS files. Parameters ---------- los_fnames : list List of filenames Returns ------- all_times : np.array Array of datetime objects with data in the files """ los_fnames = pysat.utils.listify(los_fnames) all_times = list() # Get all of the potential sites for fname in los_fnames: with h5py.File(fname, 'r') as fin: time_arr = fin['Data']['Table Layout']['ut1_unix'] # Convert from unix time to a datetime object all_times.extend([dt.datetime(1970, 1, 1) + dt.timedelta(seconds=int(time_val)) for time_val in time_arr]) return all_times