Esempio n. 1
0
 def from_SHM(self, filename, **kwargs):
     """
     Read a harmonics object from a spherical harmonic model file
     Inputs: full path of input SHM file
     Options:
         keyword arguments for SHM input
     """
     #-- set filename
     self.case_insensitive_filename(filename)
     #-- set default verbosity
     kwargs.setdefault('verbose', False)
     #-- read data from SHM file
     Ylms = read_GRACE_harmonics(self.filename, self.lmax, **kwargs)
     #-- Output file information
     logging.info(self.filename)
     logging.info(list(Ylms.keys()))
     #-- copy variables for gravity model
     self.clm = Ylms['clm'].copy()
     self.slm = Ylms['slm'].copy()
     self.time = Ylms['time'].copy()
     self.month = np.int64(calendar_to_grace(self.time))
     #-- copy header information for gravity model
     self.header = Ylms['header']
     #-- assign shape and ndim attributes
     self.update_dimensions()
     return self
Esempio n. 2
0
 def from_HDF5(self, filename, date=True, **kwargs):
     """
     Read a spatial object from a HDF5 file
     Inputs: full path of input HDF5 file
     Options:
         HDF5 file contains date information
         keyword arguments for HDF5 reader
     """
     #-- set filename
     self.case_insensitive_filename(filename)
     #-- set default parameters
     kwargs.setdefault('verbose', False)
     kwargs.setdefault('compression', None)
     kwargs.setdefault('varname', 'z')
     kwargs.setdefault('lonname', 'lon')
     kwargs.setdefault('latname', 'lat')
     kwargs.setdefault('timename', 'time')
     #-- read data from HDF5 file
     data = hdf5_read(self.filename,
                      DATE=date,
                      COMPRESSION=kwargs['compression'],
                      VARNAME=kwargs['varname'],
                      LONNAME=kwargs['lonname'],
                      LATNAME=kwargs['latname'],
                      TIMENAME=kwargs['timename'])
     #-- copy variables to spatial object
     self.data = data['data'].copy()
     if '_FillValue' in data['attributes']['data'].keys():
         self.fill_value = data['attributes']['_FillValue']
     self.mask = np.zeros(self.data.shape, dtype=bool)
     self.lon = data['lon'].copy()
     self.lat = data['lat'].copy()
     #-- if the HDF5 file contains date variables
     if date:
         self.time = data['time'].copy()
         self.month = calendar_to_grace(self.time)
         #-- adjust months to fix special cases if necessary
         self.month = adjust_months(self.month)
     #-- update attributes
     self.attributes.update(data['attributes'])
     #-- get spacing and dimensions
     self.update_spacing()
     self.update_extents()
     self.update_dimensions()
     self.update_mask()
     return self
Esempio n. 3
0
 def from_ascii(self, filename, date=True, **kwargs):
     """
     Read a spatial object from an ascii file
     Inputs: full path of input ascii file
     Options:
         ascii file contains date information
         keyword arguments for ascii input
     """
     #-- set filename
     self.case_insensitive_filename(filename)
     #-- set default parameters
     kwargs.setdefault('verbose', False)
     kwargs.setdefault('compression', None)
     kwargs.setdefault('columns', ['lon', 'lat', 'data', 'time'])
     kwargs.setdefault('header', 0)
     #-- open the ascii file and extract contents
     logging.info(self.filename)
     if (kwargs['compression'] == 'gzip'):
         #-- read input ascii data from gzip compressed file and split lines
         with gzip.open(self.filename, 'r') as f:
             file_contents = f.read().decode('ISO-8859-1').splitlines()
     elif (kwargs['compression'] == 'zip'):
         #-- read input ascii data from zipped file and split lines
         base, _ = os.path.splitext(self.filename)
         with zipfile.ZipFile(self.filename) as z:
             file_contents = z.read(base).decode('ISO-8859-1').splitlines()
     elif (kwargs['compression'] == 'bytes'):
         #-- read input file object and split lines
         file_contents = self.filename.read().splitlines()
     else:
         #-- read input ascii file (.txt, .asc) and split lines
         with open(self.filename, 'r') as f:
             file_contents = f.read().splitlines()
     #-- compile regular expression operator for extracting numerical values
     #-- from input ascii files of spatial data
     regex_pattern = r'[-+]?(?:(?:\d*\.\d+)|(?:\d+\.?))(?:[EeD][+-]?\d+)?'
     rx = re.compile(regex_pattern, re.VERBOSE)
     #-- output spatial dimensions
     if (None not in self.extent):
         self.lat = np.linspace(self.extent[3], self.extent[2],
                                self.shape[0])
         self.lon = np.linspace(self.extent[0], self.extent[1],
                                self.shape[1])
     else:
         self.lat = np.zeros((self.shape[0]))
         self.lon = np.zeros((self.shape[1]))
     #-- output spatial data
     self.data = np.zeros((self.shape[0], self.shape[1]))
     self.mask = np.zeros((self.shape[0], self.shape[1]), dtype=bool)
     #-- remove time from list of column names if not date
     columns = [c for c in kwargs['columns'] if (c != 'time')]
     #-- extract spatial data array and convert to matrix
     #-- for each line in the file
     header = kwargs['header']
     for line in file_contents[header:]:
         #-- extract columns of interest and assign to dict
         #-- convert fortran exponentials if applicable
         d = {
             c: r.replace('D', 'E')
             for c, r in zip(columns, rx.findall(line))
         }
         #-- convert line coordinates to integers
         ilon = np.int64(np.float64(d['lon']) / self.spacing[0])
         ilat = np.int64((90.0 - np.float64(d['lat'])) // self.spacing[1])
         self.data[ilat, ilon] = np.float64(d['data'])
         self.mask[ilat, ilon] = False
         self.lon[ilon] = np.float64(d['lon'])
         self.lat[ilat] = np.float64(d['lat'])
         #-- if the ascii file contains date variables
         if date:
             self.time = np.array(d['time'], dtype='f')
             self.month = calendar_to_grace(self.time)
     #-- if the ascii file contains date variables
     if date:
         #-- adjust months to fix special cases if necessary
         self.month = adjust_months(self.month)
     #-- get spacing and dimensions
     self.update_spacing()
     self.update_extents()
     self.update_dimensions()
     self.update_mask()
     return self
def convert_harmonics(INPUT_FILE,
                      OUTPUT_FILE,
                      LMAX=None,
                      MMAX=None,
                      UNITS=None,
                      LOVE_NUMBERS=0,
                      REFERENCE=None,
                      DDEG=None,
                      INTERVAL=None,
                      FILL_VALUE=None,
                      HEADER=None,
                      DATAFORM=None,
                      MODE=0o775):

    #-- verify that output directory exists
    DIRECTORY = os.path.abspath(os.path.dirname(OUTPUT_FILE))
    if not os.access(DIRECTORY, os.F_OK):
        os.makedirs(DIRECTORY, MODE, exist_ok=True)

    #-- Grid spacing
    dlon, dlat = (DDEG, DDEG) if (np.ndim(DDEG) == 0) else (DDEG[0], DDEG[1])
    #-- Grid dimensions
    if (INTERVAL == 1):  #-- (0:360, 90:-90)
        nlon = np.int64((360.0 / dlon) + 1.0)
        nlat = np.int64((180.0 / dlat) + 1.0)
    elif (INTERVAL == 2):  #-- degree spacing/2
        nlon = np.int64((360.0 / dlon))
        nlat = np.int64((180.0 / dlat))

    #-- read spatial file in data format
    #-- expand dimensions
    if (DATAFORM == 'ascii'):
        #-- ascii (.txt)
        input_spatial = spatial(spacing=[dlon, dlat],
                                nlat=nlat,
                                nlon=nlon,
                                fill_value=FILL_VALUE).from_ascii(
                                    INPUT_FILE, header=HEADER).expand_dims()
    elif (DATAFORM == 'netCDF4'):
        #-- netcdf (.nc)
        input_spatial = spatial().from_netCDF4(INPUT_FILE).expand_dims()
    elif (DATAFORM == 'HDF5'):
        #-- HDF5 (.H5)
        input_spatial = spatial().from_HDF5(INPUT_FILE).expand_dims()
    #-- convert missing values to zero
    input_spatial.replace_invalid(0.0)
    #-- input data shape
    nlat, nlon, nt = input_spatial.shape

    #-- read arrays of kl, hl, and ll Love Numbers
    LOVE = load_love_numbers(LMAX,
                             LOVE_NUMBERS=LOVE_NUMBERS,
                             REFERENCE=REFERENCE)

    #-- upper bound of spherical harmonic orders (default = LMAX)
    if MMAX is None:
        MMAX = np.copy(LMAX)

    #-- calculate associated Legendre polynomials
    th = (90.0 - input_spatial.lat) * np.pi / 180.0
    PLM, dPLM = plm_holmes(LMAX, np.cos(th))

    #-- create list of harmonics objects
    Ylms_list = []
    for i, t in enumerate(input_spatial.time):
        #-- convert spatial field to spherical harmonics
        output_Ylms = gen_stokes(input_spatial.data[:, :, i].T,
                                 input_spatial.lon,
                                 input_spatial.lat,
                                 UNITS=UNITS,
                                 LMIN=0,
                                 LMAX=LMAX,
                                 MMAX=MMAX,
                                 PLM=PLM,
                                 LOVE=LOVE)
        output_Ylms.time = np.copy(t)
        output_Ylms.month = calendar_to_grace(t)
        #-- append to list
        Ylms_list.append(output_Ylms)
    #-- convert Ylms list for output spherical harmonics
    Ylms = harmonics().from_list(Ylms_list)
    Ylms_list = None

    #-- outputting data to file
    if (DATAFORM == 'ascii'):
        #-- ascii (.txt)
        Ylms.to_ascii(OUTPUT_FILE)
    elif (DATAFORM == 'netCDF4'):
        #-- netCDF4 (.nc)
        Ylms.to_netCDF4(OUTPUT_FILE)
    elif (DATAFORM == 'HDF5'):
        #-- HDF5 (.H5)
        Ylms.to_HDF5(OUTPUT_FILE)
    #-- change output permissions level to MODE
    os.chmod(OUTPUT_FILE, MODE)
Esempio n. 5
0
 def from_ascii(self, filename, **kwargs):
     """
     Read a harmonics object from an ascii file
     Inputs: full path of input ascii file
     Options:
         ascii file contains date information
         keyword arguments for ascii input
     """
     #-- set filename
     self.case_insensitive_filename(filename)
     #-- set default parameters
     kwargs.setdefault('date', True)
     kwargs.setdefault('verbose', False)
     kwargs.setdefault('compression', None)
     #-- open the ascii file and extract contents
     logging.info(self.filename)
     if (kwargs['compression'] == 'gzip'):
         #-- read input ascii data from gzip compressed file and split lines
         with gzip.open(self.filename, 'r') as f:
             file_contents = f.read().decode('ISO-8859-1').splitlines()
     elif (kwargs['compression'] == 'zip'):
         #-- read input ascii data from zipped file and split lines
         base, _ = os.path.splitext(self.filename)
         with zipfile.ZipFile(self.filename) as z:
             file_contents = z.read(base).decode('ISO-8859-1').splitlines()
     elif (kwargs['compression'] == 'bytes'):
         #-- read input file object and split lines
         file_contents = self.filename.read().splitlines()
     else:
         #-- read input ascii file (.txt, .asc) and split lines
         with open(self.filename, 'r') as f:
             file_contents = f.read().splitlines()
     #-- compile regular expression operator for extracting numerical values
     #-- from input ascii files of spherical harmonics
     regex_pattern = r'[-+]?(?:(?:\d*\.\d+)|(?:\d+\.?))(?:[EeD][+-]?\d+)?'
     rx = re.compile(regex_pattern, re.VERBOSE)
     #-- find maximum degree and order of harmonics
     self.lmax = 0
     self.mmax = 0
     #-- for each line in the file
     for line in file_contents:
         if kwargs['date']:
             l1, m1, clm1, slm1, time = rx.findall(line)
         else:
             l1, m1, clm1, slm1 = rx.findall(line)
         #-- convert line degree and order to integers
         l1, m1 = np.array([l1, m1], dtype=np.int64)
         self.lmax = np.copy(l1) if (l1 > self.lmax) else self.lmax
         self.mmax = np.copy(m1) if (m1 > self.mmax) else self.mmax
     #-- output spherical harmonics dimensions array
     self.l = np.arange(self.lmax + 1)
     self.m = np.arange(self.mmax + 1)
     #-- output spherical harmonics data
     self.clm = np.zeros((self.lmax + 1, self.mmax + 1))
     self.slm = np.zeros((self.lmax + 1, self.mmax + 1))
     #-- if the ascii file contains date variables
     if kwargs['date']:
         self.time = np.float64(time)
         self.month = np.int64(calendar_to_grace(self.time))
         #-- adjust months to fix special cases if necessary
         self.month = adjust_months(self.month)
     #-- extract harmonics and convert to matrix
     #-- for each line in the file
     for line in file_contents:
         if kwargs['date']:
             l1, m1, clm1, slm1, time = rx.findall(line)
         else:
             l1, m1, clm1, slm1 = rx.findall(line)
         #-- convert line degree and order to integers
         ll, mm = np.array([l1, m1], dtype=np.int64)
         #-- convert fortran exponentials if applicable
         self.clm[ll, mm] = np.float64(clm1.replace('D', 'E'))
         self.slm[ll, mm] = np.float64(slm1.replace('D', 'E'))
     #-- assign shape and ndim attributes
     self.update_dimensions()
     return self