def __init__(self, filename, title='', qual=''): ''' "Opens" the given NetCDF dataset file in Ferret using the Ferret "USE" command. Creates a FerVar for each data variable in this data file and assigns it as an attribute of this class using the variable name. filename (string): name of the dataset filename or http address title (string): title for the dataset for plots and listing; if not given, the Ferret name for the dataset will be used qual (string): Ferret qualifiers to be used with the "USE" command ''' self._filename = '' self._dsetname = '' self._fervars = {} self._fervarnames = set() if not filename: if qual == _anonymous_dataset_qualifier: # initialize an new anonymous dataset that will either be # pyferret.anondset or will be modified by a subclass (FerAggDSet) return else: raise ValueError( 'pyferret.anondset should be used for the anonymous dataset' ) # tell Ferret to open/use this dataset cmdstr = 'USE' if title: cmdstr += '/TITLE="' + str(title) + '"' if qual: cmdstr += str(qual) cmdstr += ' "' + str(filename) + '"' (errval, errmsg) = pyferret.run(cmdstr) if errval != pyferret.FERR_OK: raise ValueError(errmsg) # record the filename and Ferret dataset name self._filename = filename # need to use the filename as given as the dataset name to avoid possible abiguity self._dsetname = filename # create a FerVar for each variable in this dataset namesdict = pyferret.getstrdata('..varnames') for varname in namesdict['data'].flatten(): if sys.version_info[0] > 2: # For Python3.x, namesdict['data'] is a NumPy array of bytes; convert to unicode varname = str(varname, 'UTF-8') # create a FerVar representing this existing Ferret file variable filevar = pyferret.FerVar() filevar._markasknownvar(varname, self._dsetname, True) # assign this FerVar - uppercase the variable name keys to make case-insensitive self._fervars[varname.upper()] = filevar # keep a original-case version of the name self._fervarnames.add(varname)
def diagform(self): ''' Returns an anonymous FerVar that is the transformation of this FerFMRCVar to a "diagonal" form, where the T (time) axis is the date forecasted and the F (forecast) axis is the date the forecast was made. ''' if (not self._varname) or (not self._dsetname): raise ValueError('Invalid FerFMRCVar object') # TF_TIMES is an automatically generated variable for FMRC datasets in Ferret # TF_CAL_T is an automatically generated axis for FMRC datasets in Ferret diagdefn = '%s[gt(TF_TIMES)=TF_CAL_T]' % self._varname title = self._title + ' (diag form)' diagvar = pyferret.FerVar(defn=diagdefn, title=title) diagvar._requires.add(self._varname.upper()) diagvar._requires.add("TF_TIMES") return diagvar
def leadform(self): ''' Returns an anonymous FerVar that is the transformation of this FerFMRCVar to the "lead" form, where the T (time) axis is the date forecasted and the F (forecast) axis is the lead time for the date forecasted (forecasted time minus time that the forecast was made). ''' if (not self._varname) or (not self._dsetname): raise ValueError('Invalid FerFMRCVar object') # TF_TIMES is an automatically generated variable for FMRC datasets in Ferret # TF_CAL_T is an automatically generated axis for FMRC datasets in Ferret # TF_LAG_F is an automatically generated axis for FMRC datasets in Ferret leaddefn = '%s[gt(TF_TIMES)=TF_CAL_T,gf(TF_TIMES)=TF_LAG_F]' % self._varname title = self._title + ' (lead form)' leadvar = pyferret.FerVar(defn=leaddefn, title=title) leadvar._requires.add(self._varname.upper()) leadvar._requires.add("TF_TIMES") return leadvar
def __init__(self, name, dsets, along='T', title='', warn=True, hide=False): ''' Aggregates the given list of datasets along the given axis using the Ferret "DEFINE DATA /AGGREGATE" command. Creates a FerVar for each data variable in common among these datasets, and assigns it as an attribute of this class instance using the variable name. name (string): Ferret name for this aggregated dataset dsets (sequence of strings and/or FerDSets): datasets to aggregate. A string will be interpreted as a filename for creating a FerDSet. along ('T', 'E', 'F'): axis along which to aggregate the datasets title (string): title for the dataset for plots and listing; if not given, the Ferret name for the dataset will be used warn (bool): issue warning messages about variables not in common among all member datasets (either not present or not using the same grid) hide (bool): hide the member datasets in standard Ferret listings such as with pyferret.showdata() ''' # Create an empty dataset with the given Ferret name super(FerAggDSet, self).__init__('', qual=_anonymous_dataset_qualifier) if not isinstance(name, str): raise ValueError( 'Ferret name for the aggregate dataset must be astring') aggname = name.strip() if not aggname: raise ValueError('Ferret name for the aggregate dataset is blank') self._filename = aggname self._dsetname = aggname # Need to keep the given order of component datasets self._compdsetnames = [] # But still use a dictionary with uppercase names for keys self._compdsets = {} # Create the DEFINE DATA /AGGREGATE Ferret command, creating # and saving component FerDSets as needed if along not in ('T', 'E', 'F'): raise ValueError("along must be one of 'T', 'E', or 'F'") self._along = along self._comphidden = bool(hide) cmdstr = 'DEFINE DATA/AGGREGATE/' + self._along if title: cmdstr += '/TITLE="' + str(title) + '"' if not warn: cmdstr += '/QUIET' if self._comphidden: cmdstr += '/HIDE' cmdstr += ' ' + aggname + ' = ' firstone = True if not (isinstance(dsets, tuple) or isinstance(dsets, list)): raise ValueError( 'dsets must be a tuple or list of strings and/or FerDSets') for myitem in dsets: if isinstance(myitem, str): mydset = pyferret.FerDSet(myitem) elif isinstance(myitem, pyferret.FerDSet): mydset = myitem else: raise ValueError( 'dsets must be a tuple or list of strings and/or FerDSets') if mydset._dsetname.upper() in self._compdsets: raise ValueError('duplicate dataset name ' + mydset._dsetname) if not firstone: cmdstr += ', ' else: firstone = False cmdstr += mydset._dsetname self._compdsetnames.append(mydset._dsetname) self._compdsets[mydset._dsetname.upper()] = mydset (errval, errmsg) = pyferret.run(cmdstr) if errval != pyferret.FERR_OK: raise ValueError(errmsg) # create a FerVar for each variable in this dataset namesdict = pyferret.getstrdata('..varnames') for varname in namesdict['data'].flatten(): # create a FerVar representing this existing Ferret aggregated file variable filevar = pyferret.FerVar() filevar._markasknownvar(varname, self._dsetname, True) # assign this FerVar - uppercase the variable name keys to make case-insensitive self._fervars[varname.upper()] = filevar # keep a original-case version of the name self._fervarnames.add(varname)
def __init__(self, name, dsets, along='T', title='', warn=True, hide=False): ''' Aggregates the given list of datasets along the given axis using the Ferret "DEFINE DATA /AGGREGATE" command. Creates a FerVar for each data variable in common among these datasets, and assigns it as an attribute of this class instance using the variable name. name (string): Ferret name for this aggregated dataset dsets (sequence of strings and/or FerDSets): datasets to aggregate. A string will be interpreted as a filename for creating a FerDSet. along ('T', 'E', 'F'): axis along which to aggregate the datasets title (string): title for the dataset for plots and listing; if not given, the Ferret name for the dataset will be used warn (bool): issue warning messages about variables not in common among all member datasets (either not present or not using the same grid) hide (bool): hide the member datasets in standard Ferret listings such as with pyferret.showdata() ''' # Create an empty dataset with the given Ferret name super(FerAggDSet, self).__init__('', qual=_anonymous_dataset_qualifier) if not isinstance(name, str): raise ValueError('Ferret name for the aggregate dataset must be astring') aggname = name.strip() if not aggname: raise ValueError('Ferret name for the aggregate dataset is blank') self._filename = aggname self._dsetname = aggname # Need to keep the given order of component datasets self._compdsetnames = [ ] # But still use a dictionary with uppercase names for keys self._compdsets = { } if along not in ('T', 'E', 'F'): raise ValueError("along must be one of 'T', 'E', or 'F'") self._along = along self._comphidden = bool(hide) # Create a Ferret string variable containing all the dataset names to be aggregated if not ( isinstance(dsets, tuple) or isinstance(dsets, list) ): raise ValueError('dsets must be a tuple or list of strings and/or FerDSets') filesfile = tempfile.NamedTemporaryFile(mode='w', delete=False, prefix=aggname + '_', suffix='_agg.txt') filesfilename = filesfile.name deletefilesfile = True try: for myitem in dsets: if isinstance(myitem, str): mydset = pyferret.FerDSet(myitem) elif isinstance(myitem, pyferret.FerDSet): mydset = myitem else: raise ValueError('dsets must be a tuple or list of strings and/or FerDSets') if mydset._dsetname.upper() in self._compdsets: raise ValueError('duplicate dataset name ' + mydset._dsetname) print(mydset._dsetname, file=filesfile) self._compdsetnames.append(mydset._dsetname) self._compdsets[mydset._dsetname.upper()] = mydset deletefilesfile = False finally: filesfile.close() if deletefilesfile: os.unlink(filesfilename) filesvarname = aggname + "_datafile_names" cmdstr = 'LET ' + filesvarname + ' = SPAWN("cat \'' + filesfilename + '\'")' (errval, errmsg) = pyferret.run(cmdstr) if errval != pyferret.FERR_OK: os.unlink(filesfilename) raise ValueError(errmsg) # filesfile not read (SPAWN command executed) until filesvarname is needed # Create the DEFINE DATA /AGGREGATE Ferret command, creating # and saving component FerDSets as needed cmdstr = 'DEFINE DATA/AGGREGATE/' + self._along if title: cmdstr += '/TITLE="' + str(title) + '"' if not warn: cmdstr += '/QUIET' if self._comphidden: cmdstr += '/HIDE' cmdstr += ' ' + aggname + ' = ' + filesvarname (errval, errmsg) = pyferret.run(cmdstr) # filesfile now read so can delete it os.unlink(filesfilename) if errval != pyferret.FERR_OK: raise ValueError(errmsg) # create a FerVar for each variable in this dataset namesdict = pyferret.getstrdata('..varnames') for varname in namesdict['data'].flatten(): if sys.version_info[0] > 2: # For Python3.x, namesdict['data'] is a NumPy array of bytes; convert to unicode varname = str(varname, 'UTF-8') # create a FerVar representing this existing Ferret aggregated file variable filevar = pyferret.FerVar() filevar._markasknownvar(varname, self._dsetname, True) # assign this FerVar - uppercase the variable name keys to make case-insensitive self._fervars[varname.upper()] = filevar # keep a original-case version of the name self._fervarnames.add(varname)