Source code for ocmw.dataman.dataReaders

# -*- coding: utf-8 -*-

"""
Functions to simplify the interrogation of NetCDF4 files.
"""

#Generic base data format class structures for building loaders for specific 
#data set.
#
#:Dependencies [External]: os, numpy, netCDF4
#:Dependencies [Internal]: 

# ----------------------------------------------------------------------------
#   IMPORTS
# ----------------------------------------------------------------------------
# Standard Python Dependencies
import os
# Non-Standard Python Dependencies
import numpy as np
from netCDF4 import Dataset as ncdata
from netCDF4 import date2num, num2date
# Local Module Dependencies
from ocmw.core.timeFuncs import datetime, stdTimeUnits
from ocmw.core.geometry import spatialCoverage
# Other Dependencies

# ----------------------------------------------------------------------------
#   GLOBAL VARIABLES
# ----------------------------------------------------------------------------


# ----------------------------------------------------------------------------
#   CLASS DEFINITIONS
# ----------------------------------------------------------------------------

# ============ Generic netCDF Reader ====================================
[docs] class netcdfGeneric: """ Base class for loading and interogating netCDF4 data files. """ def __init__(self, fileName): self.file = {} if os.path.isfile(fileName): self.file.update({'name': fileName}) with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: self.file.update({'attribs': nc.ncattrs()}) dimNames = [] for key in nc.dimensions.keys(): dimNames.append(nc.dimensions[key].name) self.file.update({'dims': dimNames}) self.file.update({'vars': list(nc.variables)}) else: self.file.update({'name': ''}) self.file.update({'attribs': []}) self.file.update({'vars': []}) print('WARNING: File '+fileName+' does not exist.')
[docs] def listGlobalAttr(self): with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: attrList = nc.ncattrs() return attrList
[docs] def hasGlobalAttr(self, attrName): return attrName in self.file['attribs']
[docs] def getGlobalAttr(self, attrName): if self.hasGlobalAttr(attrName): with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: attrib = nc.__getattr__(attrName) else: print('WARNING: Global Attribute '+attrName+' does not exist.') print('Available global attributes:') print(list(self.file['attribs'])) attrib = None return attrib
[docs] def listDims(self): dimsList = [] with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: for key in nc.dimensions.keys(): dimsList.append(nc.dimensions[key].name) return dimsList
[docs] def hasDim(self, dimName): return dimName in self.file['dims']
[docs] def getDim(self, dimName): if self.hasDim(dimName): with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: dimSize = nc.dimensions[dimName].size else: print('WARNING: Dimension '+dimName+' does not exist.') print('Available dimensions:') print(list(self.file['dims'])) dimSize = None return dimSize
[docs] def listVars(self): with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: varList = list(nc.variables) return varList
[docs] def hasVar(self, varName): return varName in self.file['vars']
[docs] def listVarAttrs(self, varName): if self.hasVar(varName): with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: attrList = nc.variables[varName].ncattrs() else: print('WARNING: Variable '+varName+' does not exist.') print('Available variables:') print(list(self.file['vars'])) attrList = [] return attrList
[docs] def hasVarAttr(self, varName, attrName): attrList = self.listVarAttrs(varName) return attrName in attrList
[docs] def getVarAttr(self, varName, attrName): if varName in self.file['vars']: if self.hasVarAttr(varName, attrName): with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: attr = nc.variables[varName].getncattr(attrName) else: print('WARNING: Attribute '+attrName+' does not exist.') print('Available attributes:') print(list(self.listVarAttrs(varName))) attr = None else: print('WARNING: Variable '+varName+' does not exist.') print('Available variables:') print(list(self.file['vars'])) attr = None return attr
[docs] def getVarDimNames(self, varName): if self.hasVar(varName): with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: dimNames = list(nc.variables[varName].dimensions) else: print('WARNING: Variable '+varName+' does not exist.') print('Available variables:') print(list(self.file['vars'])) dimNames = None return dimNames
[docs] def getVarDimSizes(self, varName): if self.hasVar(varName): with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: dimSizes = list(nc.variables[varName].shape) else: print('WARNING: Variable '+varName+' does not exist.') print('Available variables:') print(list(self.file['vars'])) dimSizes = None return dimSizes
[docs] def getVar(self, varName): if self.hasVar(varName): with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: if np.ma.isMaskedArray(nc.variables[varName][:]): var = np.ma.getdata(nc.variables[varName][:]) else: var = nc.variables[varName][:] if var.dtype == '|S1': var = (b''.join(list(var))).decode('utf-8') else: print('WARNING: Variable '+varName+' does not exist.') print('Available variables:') print(list(self.file['vars'])) var = None return var
[docs] def updateVar(self, varName, vals): if varName in self.file['vars']: nc = ncdata(self.file['name'], 'r+') nc.variables[varName][:] = vals nc.close() else: print('WARNING: Variable '+varName+' does not exist.') print('Available variables:') print(list(self.file['vars'])) return
[docs] def updateVarAttr(self, varName, varAttr, vals): if self.hasVarAttr(varName,varAttr): nc = ncdata(self.file['name'], 'r+') nc.variables[varName].setncattr(varName,vals) nc.close() else: print('WARNING: Variable '+varName+' does not have attribute '+varAttr+'.') print('Available variables:') print(list(self.listVarAttr(varName))) return
[docs] def updateGlobalAttr(self, attrName, val): if self.hasGlobalAttr(attrName): nc = ncdata(self.file['name'], 'r+') nc.__getattr__(attrName,val) nc.close() else: print('WARNING: Global attribure '+attrName+' does not exist.') print('Available attributes:') print(list(self.listGlobalAttr)) return
# ============ ResourceCode WW3 Model Output Files ======================
[docs] class ww3(netcdfGeneric): """ Class structure for reading the ResourceCode WW3 model output netCDF files. """ def __init__(self, fileName): netcdfGeneric.__init__(self, fileName) if self.file['name'] != '': if 'station_name' in self.file['vars']: self.platform = \ "".join([s.decode('utf-8') for s in (self.getVar('station_name')[0])]) if 'start_date' in self.file['attribs']: tstr = ncdata(fileName).start_date self.time_start = tstr.replace('T', ' ').replace('Z', '') if 'stop_date' in self.file['attribs']: tstr = ncdata(fileName).stop_date self.time_end = tstr.replace('T', ' ').replace('Z', '') if 'latitude' in self.file['vars']: self.lat_min = np.nanmin(self.getVar('latitude')) self.lat_max = np.nanmax(self.getVar('latitude')) lat = np.nanmean(self.getVar('latitude')) self.lat = int(lat*100000.0)/100000.0 if 'longitude' in self.file['vars']: self.lon_min = np.nanmin(self.getVar('longitude')) self.lon_max = np.nanmax(self.getVar('longitude')) lon = np.nanmean(self.getVar('longitude')) self.lon = int(lon*100000.0)/100000.0 if 'time' in self.file['vars']: t = self.getVar('time') p = np.mean(np.diff(t))*24.0 self.sample_period = int(p*3600.0)/3600.0
[docs] def getMetaData(self): path, file = os.path.split(self.file['name']) dtFmt = '%Y-%m-%d %H:%M:%S' year = datetime.strptime(self.time_start, dtFmt).year month = datetime.strptime(self.time_start, dtFmt).month meta = [self.platform, path, file, self.lat, self.lon, self.time_start, self.time_end, year, month, self.sample_period] return meta
[docs] def getVar(self, varName): if varName in self.file['vars']: with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: if varName == 'time': timeUnits = self.getVarAttr('time', 'units') if np.ma.isMaskedArray(nc.variables[varName][:]): time = np.ma.getdata(nc.variables[varName][:]) else: time = nc.variables[varName][:] var = date2num(num2date(time, timeUnits), stdTimeUnits) else: if np.ma.isMaskedArray(nc.variables[varName][:]): var = np.ma.getdata(nc.variables[varName][:]) else: var = nc.variables[varName][:] if self.hasVarAttr(varName,'_FillValue'): fv = self.getVarAttr(varName,'_FillValue') var[var==fv] = np.NaN else: print('WARNING: Variable '+varName+' does not exist.') print('Available variables:') print(list(self.file['vars'])) var = None return var
[docs] class ww3Mesh: """ Class structure for extracting the model mesh data from the a ResourceCode WW3 model output netCDF files that contains the mesh definition. """ def __init__(self, meshFile): try: mesh = ww3(meshFile) lon = mesh.getVar('longitude') lat = mesh.getVar('latitude') elems = mesh.getVar('tri') bathy = mesh.getVar('dpt') self.domain = spatialCoverage(np.nanmin(lat), np.nanmax(lat), np.nanmin(lon), np.nanmax(lon)) self.X = lon self.Y = lat self.elems = elems self.bathy = bathy except: print('WARNING: An error occurred while extracting mesh.') self.domain = None self.X = None self.Y = None self.elems = None self.bathy = None
# ============ Marine Scotland SSW Model Output Files ===================
[docs] class ssw_rs(netcdfGeneric): """ Class structure for reading the Marine Scotland SSW model output netCDF files. """ def __init__(self, fileName): netcdfGeneric.__init__(self, fileName) if self.file['name'] != '': # set metadata platform self.platform = None # set metadata start date t = self.getVar('time')[0] units = self.getVarAttr('time','units') self.time_start = num2date(t,units).strftime() # set metadata stop date t = self.getVar('time')[-1] units = self.getVarAttr('time','units') self.time_end = num2date(t,units).strftime() if 'lat' in self.file['vars']: self.lat_min = np.nanmin(self.getVar('lat')) self.lat_max = np.nanmax(self.getVar('lat')) lat = np.nanmean(self.getVar('lat')) self.lat = int(lat*100000.0)/100000.0 if 'lon' in self.file['vars']: self.lon_min = np.nanmin(self.getVar('lon')) self.lon_max = np.nanmax(self.getVar('lon')) lon = np.nanmean(self.getVar('lon')) self.lon = int(lon*100000.0)/100000.0 if 'time' in self.file['vars']: t = self.getVar('time') p = np.mean(np.diff(t))*24.0 self.sample_period = int(p*3600.0)/3600.0
[docs] def getMetaData(self): path, file = os.path.split(self.file['name']) dtFmt = '%Y-%m-%d %H:%M:%S' year = datetime.strptime(self.time_start, dtFmt).year month = datetime.strptime(self.time_start, dtFmt).month meta = [self.platform, path, file, self.lat, self.lon, self.time_start, self.time_end, year, month, self.sample_period] return meta
[docs] def getVar(self, varName): if varName in self.file['vars']: with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: if varName == 'time': timeUnits = self.getVarAttr('time', 'units') if np.ma.isMaskedArray(nc.variables[varName][:]): time = np.ma.getdata(nc.variables[varName][:]) else: time = nc.variables[varName][:] var = date2num(num2date(time, timeUnits), stdTimeUnits) elif varName in ['lon','lonc']: if np.ma.isMaskedArray(nc.variables[varName][:]): var = np.ma.getdata(nc.variables[varName][:]) else: var = nc.variables[varName][:] var[var > 180.0] = var[var > 180.0] -360.0 else: if np.ma.isMaskedArray(nc.variables[varName][:]): var = np.ma.getdata(nc.variables[varName][:]) else: var = nc.variables[varName][:] if self.hasVarAttr(varName,'_FillValue'): fv = self.getVarAttr(varName,'_FillValue') var[var==fv] = np.NaN else: print('WARNING: Variable '+varName+' does not exist.') print('Available variables:') print(list(self.file['vars'])) var = None return var
[docs] class sswMesh: """ Class structure for extracting the model mesh data from the a Marine Scotland SSW model output netCDF files that contains the mesh definition. """ def __init__(self, sswFile): try: ssw = ssw_rs(sswFile) lon = ssw.getVar('lon') lat = ssw.getVar('lat') elems = np.transpose(ssw.getVar('nv')) self.domain = spatialCoverage(np.nanmin(lat), np.nanmax(lat), np.nanmin(lon), np.nanmax(lon)) self.X = lon self.Y = lat self.elems = elems self.Xc = ssw.getVar('lonc') self.Yc = ssw.getVar('latc') self.bathy = ssw.getVar('h') self.bathyc = ssw.getVar('h_center') except: print('WARNING: An error occurred while extracting mesh.') self.domain = None self.X = None self.Y = None self.elems = None self.Xc = None self.Yc = None self.bathy = None self.bathyc = None
# ==================== OceanSites Moored Buoy Data ======================
[docs] class wavebuoy(netcdfGeneric): """ Class structure for reading the CMEMS formatted wavebuoy netCDF files. """ def __init__(self, fileName): netcdfGeneric.__init__(self, fileName) if self.file['name'] != '': if 'platform_code' in self.file['attribs']: self.platform = ncdata(fileName).platform_code if 'time_coverage_start' in self.file['attribs']: tstr = ncdata(fileName).time_coverage_start self.time_start = tstr.replace('T', ' ').replace('Z', '') if 'time_coverage_end' in self.file['attribs']: tstr = ncdata(fileName).time_coverage_end self.time_end = tstr.replace('T', ' ').replace('Z', '') if 'LATITUDE' in self.file['vars']: self.lat_min = np.nanmin(self.getVar('LATITUDE')) self.lat_max = np.nanmax(self.getVar('LATITUDE')) lat = np.nanmedian(self.getVar('LATITUDE')) self.lat = int(lat*100000.0)/100000.0 if 'LONGITUDE' in self.file['vars']: self.lon_min = np.nanmin(self.getVar('LONGITUDE')) self.lon_max = np.nanmax(self.getVar('LONGITUDE')) lon = np.nanmedian(self.getVar('LONGITUDE')) self.lon = int(lon*100000.0)/100000.0 if 'TIME' in self.file['vars']: t = self.getVar('TIME') p = np.median(np.diff(t))*24.0 self.sample_period = round(p*3600.0)/3600.0
[docs] def getMetaData(self): path, file = os.path.split(self.file['name']) meta = [self.platform, path, file, self.lat, self.lon, self.time_start, self.time_end, self.sample_period] return meta
[docs] def getVar(self, varName): if varName in self.file['vars']: with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: if varName == 'TIME': timeUnits = self.getVarAttr('TIME', 'units') time, mask = get_nc_var(nc, 'TIME') var = date2num(num2date(time, timeUnits), stdTimeUnits) var[mask] = np.nan else: var, mask = get_nc_var(nc, varName) if mask is not None: var[mask] = np.nan if self.hasVarAttr(varName,'_FillValue'): fv = self.getVarAttr(varName,'_FillValue') var[var==fv] = np.NaN else: print('WARNING: Variable '+varName+' does not exist.') print('Available variables:') print(list(self.file['vars'])) var = None return var
[docs] def getQCVar(self, varName): if varName in self.file['vars']: if varName == 'TIME': timeUnits = self.getVarAttr('TIME', 'units') with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: times, t_mask = get_nc_var(nc, 'TIME') tqc, tqc_mask = get_nc_var(nc, 'TIME_QC') var = date2num(num2date(times, timeUnits), stdTimeUnits) t_unique, indx, cnts = np.unique(times, return_index=True, return_counts=True) umask = np.ones(tqc.shape, dtype=bool) umask[np.sort(indx[cnts == 1])] = False tmask = tqc_mask mask = tmask | umask else: with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: var, v_mask = get_nc_var(nc, varName) vqc, vqc_mask = get_nc_var(nc, varName+'_QC') vqc, vqc_mask = get_nc_var(nc, varName+'_QC') var[v_mask] = np.nan var[vqc != 1] = np.nan mask = np.zeros(vqc.shape, dtype=bool) mask[np.isnan(var)] = True else: print('WARNING: Variable '+varName+' does not exist.') print('Available variables:') print(list(self.file['vars'])) var = mask = None return var, mask
[docs] def getQCTimeseries(self, varName, varIndex): t, tmsk = self.getQCVar('TIME') v, vmsk = self.getQCVar(varName) msk = tmsk | vmsk[:, varIndex] times = t[~msk].copy() values = v[:, varIndex].copy() values = values[~msk] return times, values
[docs] def gapFillTimeseries(self, times, values): return times, values
# ==================== EMEC Moored Buoy Data SeaDataNet ======================
[docs] class emecwb(netcdfGeneric): """ Class structure for reading the EMEC formatted wavebuoy netCDF files. """ def __init__(self, fileName): netcdfGeneric.__init__(self, fileName) if self.file['name'] != '': if 'SDN_STATION' in self.file['vars']: self.platform = str(self.getVar('SDN_STATION')) else: self.platform = 'unknown' if 'LATITUDE' in self.file['vars']: self.lat_min = np.nanmin(self.getVar('LATITUDE')) self.lat_max = np.nanmax(self.getVar('LATITUDE')) lat = np.nanmedian(self.getVar('LATITUDE')) self.lat = int(lat*100000.0)/100000.0 if 'LONGITUDE' in self.file['vars']: self.lon_min = np.nanmin(self.getVar('LONGITUDE')) self.lon_max = np.nanmax(self.getVar('LONGITUDE')) lon = np.nanmedian(self.getVar('LONGITUDE')) self.lon = int(lon*100000.0)/100000.0 if 'TIME' in self.file['vars']: t = self.getVar('TIME').squeeze() p = np.median(np.diff(t))*24.0 self.sample_period = round(p*3600.0)/3600.0 self.time_start = num2date(t[0], stdTimeUnits).strftime() self.time_end = num2date(t[-1], stdTimeUnits).strftime()
[docs] def getMetaData(self): path, file = os.path.split(self.file['name']) meta = [self.platform, path, file, self.lat, self.lon, self.time_start, self.time_end, self.sample_period] return meta
[docs] def getVar(self, varName): if varName in self.file['vars']: with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: if varName == 'TIME': timeUnits = self.getVarAttr('TIME', 'units') time, mask = get_nc_var(nc, 'TIME') var = date2num(num2date(time, timeUnits), stdTimeUnits) var[mask] = np.nan else: var, mask = get_nc_var(nc, varName) if mask is not None: var[mask] = np.nan if self.hasVarAttr(varName,'_FillValue'): fv = self.getVarAttr(varName,'_FillValue') var[var==fv] = np.NaN if var.dtype == '|S1': var = (b''.join(list(var))).decode('utf-8') var = np.squeeze(var) else: print('WARNING: Variable '+varName+' does not exist.') print('Available variables:') print(list(self.file['vars'])) var = None return var
[docs] def getQCVar(self, varName): if varName in self.file['vars']: if varName == 'TIME': timeUnits = self.getVarAttr('TIME', 'units') with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: times, t_mask = get_nc_var(nc, 'TIME') tqc, tqc_mask = get_nc_var(nc, 'TIME_SEADATANET_QC') var = date2num(num2date(times, timeUnits), stdTimeUnits) t_unique, indx, cnts = np.unique(times, return_index=True, return_counts=True) umask = np.ones(tqc.shape, dtype=bool) umask[np.sort(indx[cnts == 1])] = False tmask = tqc_mask mask = tmask | umask var = np.squeeze(var) mask = np.squeeze(mask) else: with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: var, v_mask = get_nc_var(nc, varName) vqc, vqc_mask = get_nc_var(nc, varName+'_SEADATANET_QC') #vqc, vqc_mask = get_nc_var(nc, varName+'_SEADATANET_QC') var[v_mask] = np.nan var[vqc > 49] = np.nan mask = np.zeros(vqc.shape, dtype=bool) mask[np.isnan(var)] = True var = np.squeeze(var) mask = np.squeeze(mask) else: print('WARNING: Variable '+varName+' does not exist.') print('Available variables:') print(list(self.file['vars'])) var = mask = None return var, mask
[docs] def getQCTimeseries(self, varName, varIndex): t, tmsk = self.getQCVar('TIME') v, vmsk = self.getQCVar(varName) msk = tmsk | vmsk times = t[~msk].copy() values = v.copy() values = values[~msk] return times, values
[docs] def gapFillTimeseries(self, times, values): return times, values
# ====================== OceanSites Drifter Data ======================
[docs] class drifter(netcdfGeneric): """ Class structure for reading the CMEMS formatted drifter netCDF files. """ def __init__(self, fileName): netcdfGeneric.__init__(self, fileName) if self.file['name'] != '': if 'platform_code' in self.file['attribs']: self.platform = ncdata(fileName).platform_code if 'time_coverage_start' in self.file['attribs']: tstr = ncdata(fileName).time_coverage_start self.time_start = tstr.replace('T', ' ').replace('Z', '') if 'time_coverage_end' in self.file['attribs']: tstr = ncdata(fileName).time_coverage_end self.time_end = tstr.replace('T', ' ').replace('Z', '') if 'LATITUDE' in self.file['vars']: self.lat_min = np.nanmin(self.getVar('LATITUDE')) self.lat_max = np.nanmax(self.getVar('LATITUDE')) lat = np.nanmedian(self.getVar('LATITUDE')) self.lat = int(lat*100000.0)/100000.0 if 'LONGITUDE' in self.file['vars']: self.lon_min = np.nanmin(self.getVar('LONGITUDE')) self.lon_max = np.nanmax(self.getVar('LONGITUDE')) lon = np.nanmedian(self.getVar('LONGITUDE')) self.lon = int(lon*100000.0)/100000.0 if 'TIME' in self.file['vars']: t = self.getVar('TIME') p = np.median(np.diff(t))*24.0 self.sample_period = round(p*3600.0)/3600.0
[docs] def getMetaData(self): path, file = os.path.split(self.file['name']) meta = [self.platform, path, file, self.lat, self.lon, self.time_start, self.time_end, self.sample_period] return meta
[docs] def getVar(self, varName): if varName in self.file['vars']: with ncdata(self.file['name'], 'r', format='NETCDF4') as nc: if varName == 'TIME': timeUnits = self.getVarAttr('TIME', 'units') if np.ma.isMaskedArray(nc.variables[varName][:]): time = np.ma.getdata(nc.variables[varName][:]) else: time = nc.variables[varName][:] var = date2num(num2date(time, timeUnits), stdTimeUnits) else: if np.ma.isMaskedArray(nc.variables[varName][:]): var = np.ma.getdata(nc.variables[varName][:]) else: var = nc.variables[varName][:] var = nc.variables[varName][:] if self.hasVarAttr(varName,'_FillValue'): fv = self.getVarAttr(varName,'_FillValue') var[var==fv] = np.NaN else: print('WARNING: Variable '+varName+' does not exist.') print('Available variables:') print(list(self.file['vars'])) var = None return var
[docs] def getTrackCoverage(self): coverage = spatialCoverage() if (self.hasVar('LATITUDE') & self.hasVar('LONGITUDE')): coverage.lat_range[0] = np.nanmin(self.getVar('LATITUDE')) coverage.lat_range[1] = np.nanmax(self.getVar('LATITUDE')) coverage.lon_range[0] = np.nanmin(self.getVar('LONGITUDE')) coverage.lon_range[1] = np.nanmax(self.getVar('LONGITUDE')) return coverage
[docs] def crossesDomain(self, domain: spatialCoverage): # this belongs in a separate match module... crosses = False return crosses
# ---------------------------------------------------------------------------- # FUNCTION DEFINITIONS # ----------------------------------------------------------------------------
[docs] def is_masked(data): masked = type(data) == np.ma.core.MaskedArray return masked
[docs] def get_nc_var(ncHnd, varName): try: if (ncHnd[varName].valid_min == ' ') or (ncHnd[varName].valid_max == ' '): ncHnd.set_auto_mask(False) except: ncHnd.set_auto_mask(True) var = ncHnd.variables[varName][:].copy() if is_masked(var): data = np.ma.getdata(var) mask = np.ma.getmask(var) if mask.size == 1: mskval = mask mask = np.zeros(data.shape, dtype='bool') mask[:] = mskval else: data = var mask = None return data, mask
[docs] def ncread(filename, varname): with ncdata(filename,'r') as nc: if varname in list(nc.variables): if np.ma.isMaskedArray(nc.variables[varname]): var = np.ma.getdata(nc.variables[varname][:]) else: var = nc.variables[varname][:] else: var = None return var
[docs] def ncwrite(filename, varname, var): with ncdata(filename,'a') as nc: if varname in list(nc.variables): nc.variables[varname][:] = var return var
#-------------------------------------------------------------------------- # MAIN PROCESS #-------------------------------------------------------------------------- #-------------------------------------------------------------------------- # INTERFACE #--------------------------------------------------------------------------