def scan_grib(self, gribs, kwargs): v_selected = kwargs['shortName'] v_pert = kwargs.get('perturbationNumber', -1) grib_append = gribs.append if not utils.is_container(v_selected): v_selected = [v_selected] if self._grbindx: for v in v_selected: grib_index_select(self._grbindx, 'shortName', str(v)) if v_pert != -1: grib_index_select(self._grbindx, 'perturbationNumber', int(v_pert)) while 1: gid = grib_new_from_index(self._grbindx) if gid is None: break if GRIBReader._find(gid, **kwargs): grib_append(gid) else: # release unused grib grib_release(gid) elif self._file_handler: while 1: gid = grib_new_from_file(self._file_handler) if gid is None: break if GRIBReader._find(gid, **kwargs): grib_append(gid) else: # release unused grib grib_release(gid)
def grib_generator(filename, auto_regularise=True): """ Returns a generator of :class:`~iris.fileformats.grib.GribWrapper` fields from the given filename. Args: * filename (string): Name of the file to generate fields from. Kwargs: * auto_regularise (*True* | *False*): If *True*, any field defined on a reduced grid will be interpolated to an equivalent regular grid. If *False*, any field defined on a reduced grid will be loaded on the raw reduced grid with no shape information. The default behaviour is to interpolate fields on a reduced grid to an equivalent regular grid. """ with open(filename, 'rb') as grib_fh: while True: grib_message = gribapi.grib_new_from_file(grib_fh) if grib_message is None: break grib_wrapper = GribWrapper(grib_message, grib_fh, auto_regularise) yield grib_wrapper # finished with the grib message - claimed by the ecmwf c library. gribapi.grib_release(grib_message)
def get_grib_info(self, select_args): _gribs_for_utils = self._get_gids(**select_args) if len(_gribs_for_utils) > 0: type_of_step = grib_get(_gribs_for_utils[1], 'stepType') # instant, avg, cumul # FIXME this is not correct: GRIB missing values needs bitmap self._mv = grib_get_double(_gribs_for_utils[0], 'missingValue') start_grib, end_grib, self._step_grib, self._step_grib2, self._change_step_at = self._find_start_end_steps( _gribs_for_utils) for g in _gribs_for_utils: grib_release(g) _gribs_for_utils = None del _gribs_for_utils import gc gc.collect() info = GRIBInfo(input_step=self._step_grib, input_step2=self._step_grib2, change_step_at=self._change_step_at, type_of_param=type_of_step, start=start_grib, end=end_grib, mv=self._mv) return info # no messages found else: raise ValueError('No messages found in grib file')
def __exit__(self, exception_type, exception_value, traceback): """Release GRIB message handle and inform file of release.""" # This assert should never trigger # assert self.gid is not None gribapi.grib_release(self.gid) if self.grib_index: self.grib_index.open_messages.remove(self)
def check(self, dtype): data = np.random.random(1920 * 2560).astype(dtype) cube = iris.cube.Cube(data, standard_name='geopotential_height', units='km') grib_message = gribapi.grib_new_from_samples("GRIB2") data_section(cube, grib_message) gribapi.grib_release(grib_message)
def __getitem__(self, keys): with open(self.path, 'rb') as grib_fh: grib_fh.seek(self.offset) grib_message = gribapi.grib_new_from_file(grib_fh) data = _message_values(grib_message, self.shape) gribapi.grib_release(grib_message) return data.__getitem__(keys)
def close(self): for g in self._selected_grbs: grib_release(g) self._selected_grbs = None if self._grbindx: grib_index_release(self._grbindx) self._grbindx = None if self._file_handler: self._file_handler.close() self._file_handler = None
def __getitem__(self, keys): with open(self.path, "rb") as grib_fh: grib_fh.seek(self.offset) grib_message = gribapi.grib_new_from_file(grib_fh) if self.regularise and _is_quasi_regular_grib(grib_message): _regularise(grib_message) data = _message_values(grib_message, self.shape) gribapi.grib_release(grib_message) return data.__getitem__(keys)
def merge_prev_months(month, fin, fouts, writer): while True: gid = gribapi.grib_new_from_file(fin) if (not gid): break date = int(gribapi.grib_get(gid, "dataDate")) mon = (date % 10000) / 100 if (mon == month): code = make_grib_tuple(gribapi.grib_get(gid, "param")) if (code in accum_codes): continue fix_Pa_pressure_levels(gid) writer(gid, fouts) gribapi.grib_release(gid)
def __getitem__(self, keys): # Avoid fetching file data just to return an 'empty' result. # Needed because of how dask.array.from_array behaves since Dask v2.0. result = _array_slice_ifempty(keys, self.shape, self.dtype) if result is None: with open(self.path, 'rb') as grib_fh: grib_fh.seek(self.offset) grib_message = gribapi.grib_new_from_file(grib_fh) data = _message_values(grib_message, self.shape) gribapi.grib_release(grib_message) result = data.__getitem__(keys) return result
def write_lsm(gribfield_mod, input_path_oifs, output_path_oifs, exp_name_oifs, grid_name_oce, num_fields, gid): ''' This function copies the input gribfile to the output folder and modifies it by writing the whole gribfield_mod, including the altered land sea mask and soil type fields into the new file ''' input_file_oifs = input_path_oifs + 'ICMGG' + exp_name_oifs + 'INIT' output_file_oifs = output_path_oifs + 'ICMGG' + exp_name_oifs + 'INIT_' + grid_name_oce copy2(input_file_oifs, output_file_oifs) with open(output_file_oifs, 'r+') as f: for i in range(num_fields): gribapi.grib_set_values(gid[i], gribfield_mod[i]) gribapi.grib_write(gid[i], f) gribapi.grib_release(gid[i])
def grib_generator(filename, auto_regularise=True): """ Returns a generator of :class:`~iris.fileformats.grib.GribWrapper` fields from the given filename. .. deprecated:: 1.10 The function: :meth:`iris.fileformats.grib.message.GribMessage.messages_from_filename` provides alternative means of obtainig GRIB messages from a file. Args: * filename (string): Name of the file to generate fields from. Kwargs: * auto_regularise (*True* | *False*): If *True*, any field defined on a reduced grid will be interpolated to an equivalent regular grid. If *False*, any field defined on a reduced grid will be loaded on the raw reduced grid with no shape information. The default behaviour is to interpolate fields on a reduced grid to an equivalent regular grid. """ warn_deprecated('Deprecated at version 1.10') with open(filename, 'rb') as grib_fh: while True: grib_message = gribapi.grib_new_from_file(grib_fh) if grib_message is None: break grib_wrapper = GribWrapper(grib_message, grib_fh, auto_regularise) yield grib_wrapper # finished with the grib message - claimed by the ecmwf c library. gribapi.grib_release(grib_message)
def grib_generator(filename, auto_regularise=True): """ Returns a generator of :class:`~iris_grib.GribWrapper` fields from the given filename. .. deprecated:: 1.10 The function: :meth:`iris_grib.message.GribMessage.messages_from_filename` provides alternative means of obtainig GRIB messages from a file. Args: * filename (string): Name of the file to generate fields from. Kwargs: * auto_regularise (*True* | *False*): If *True*, any field defined on a reduced grid will be interpolated to an equivalent regular grid. If *False*, any field defined on a reduced grid will be loaded on the raw reduced grid with no shape information. The default behaviour is to interpolate fields on a reduced grid to an equivalent regular grid. """ warn_deprecated('Deprecated at version 1.10') with open(filename, 'rb') as grib_fh: while True: grib_message = gribapi.grib_new_from_file(grib_fh) if grib_message is None: break grib_wrapper = GribWrapper(grib_message, grib_fh, auto_regularise) yield grib_wrapper # finished with the grib message - claimed by the ecmwf c library. gribapi.grib_release(grib_message)
def save_messages(messages, target, append=False): """ Save messages to a GRIB2 file. The messages will be released as part of the save. Args: * messages: An iterable of grib_api message IDs. * target: A filename or open file handle. Kwargs: * append: Whether to start a new file afresh or add the cube(s) to the end of the file. Only applicable when target is a filename, not a file handle. Default is False. """ # grib file (this bit is common to the pp and grib savers...) if isinstance(target, six.string_types): grib_file = open(target, "ab" if append else "wb") elif hasattr(target, "write"): if hasattr(target, "mode") and "b" not in target.mode: raise ValueError("Target not binary") grib_file = target else: raise ValueError("Can only save grib to filename or writable") try: for message in messages: gribapi.grib_write(message, grib_file) gribapi.grib_release(message) finally: # (this bit is common to the pp and grib savers...) if isinstance(target, six.string_types): grib_file.close()
def save_messages(messages, target, append=False): """ Save messages to a GRIB2 file. The messages will be released as part of the save. Args: * messages: An iterable of grib_api message IDs. * target: A filename or open file handle. Kwargs: * append: Whether to start a new file afresh or add the cube(s) to the end of the file. Only applicable when target is a filename, not a file handle. Default is False. """ # grib file (this bit is common to the pp and grib savers...) if isinstance(target, str): grib_file = open(target, "ab" if append else "wb") elif hasattr(target, "write"): if hasattr(target, "mode") and "b" not in target.mode: raise ValueError("Target not binary") grib_file = target else: raise ValueError("Can only save grib to filename or writable") try: for message in messages: gribapi.grib_write(message, grib_file) gribapi.grib_release(message) finally: # (this bit is common to the pp and grib savers...) if isinstance(target, str): grib_file.close()
def plotData(): # # G R I B A P I # f = open(INPUT) gid = gribapi.grib_new_from_file(f) values = gribapi.grib_get_values(gid) # print values.dtype # print values.shape Ni = gribapi.grib_get(gid, 'Ni') Nj = gribapi.grib_get(gid, 'Nj') print 'GRIB_API: %d (%dx%d=%d) values found in %s' % (len(values), Nj, Ni, Nj * Ni, INPUT) latitudeOfFirstGridPointInDegrees = gribapi.grib_get( gid, 'latitudeOfFirstGridPointInDegrees') longitudeOfFirstGridPointInDegrees = gribapi.grib_get( gid, 'longitudeOfFirstGridPointInDegrees') latitudeOfLastGridPointInDegrees = gribapi.grib_get( gid, 'latitudeOfLastGridPointInDegrees') longitudeOfLastGridPointInDegrees = gribapi.grib_get( gid, 'longitudeOfLastGridPointInDegrees') jDirectionIncrementInDegrees = gribapi.grib_get( gid, 'jDirectionIncrementInDegrees') iDirectionIncrementInDegrees = gribapi.grib_get( gid, 'iDirectionIncrementInDegrees') # for key in ('max','min','average'): # print ' %s=%.10e' % (key,gribapi.grib_get(gid,key)) gribapi.grib_release(gid) f.close() # # M A G I C S # Magics.init() Magics.setc("OUTPUT_FORMAT", "ps") Magics.setc("OUTPUT_NAME", "py_arrays_from_grib") Magics.setr("INPUT_FIELD_INITIAL_LATITUDE", latitudeOfFirstGridPointInDegrees) Magics.setr("INPUT_FIELD_INITIAL_LONGITUDE", longitudeOfFirstGridPointInDegrees) Magics.setr("INPUT_FIELD_LATITUDE_STEP", -jDirectionIncrementInDegrees) Magics.setr("INPUT_FIELD_LONGITUDE_STEP", iDirectionIncrementInDegrees) values2 = numpy.array(values - 273.15) # convert degree K to C # print values2.dtype # print values2.shape val = values2.reshape(Nj, Ni) # print val.dtype # print val.shape Magics.set2r("INPUT_FIELD", val) # Magics.setc ("contour_grid_value_plot", "on") # Magics.setc ("contour_grid_value_plot_type", "value") # Magics.seti ("contour_grid_value_lat_frequency", 8) # Magics.seti ("contour_grid_value_lon_frequency", 8) # Magics.setr ("contour_grid_value_height", 0.3) # Magics.setc ("contour", "off") Magics.cont() Magics.coast() Magics.finalize()
def __exit__(self, type, value, traceback): """Release GRIB message handle and inform file of release.""" gribapi.grib_release(self.gid) if self.grib_index: self.grib_index.open_messages.remove(self)
def __del__(self): """ Release the gribapi reference to the message at end of object's life. """ gribapi.grib_release(self._message_id)
# missingValue=gribapi.grib_get(gidPlot,"missingValue") # values=gribapi.grib_get_values(gidPlot) # msg=np.reshape(values,(Nj,Ni),'C') # msgmasked = np.ma.masked_values(msg,missingValue) # xx,yy=np.meshgrid(lons,lats) # map = Basemap(llcrnrlon=250,llcrnrlat=-10,urcrnrlon=310,urcrnrlat=40) # map.drawcoastlines() # map.drawcountries() # cs=map.contourf(xx,yy,msgmasked) # map.colorbar(cs) # plt.show() ##### # RELEASE ALL MESSAGES for i in range(mcount): gribapi.grib_release(i + 1) ##### # OPEN OUTPUT FILE fout = open(outFile, 'w') ##### # WRITE RECORDS writeRec1() writeRec2() writeRec3() writeRec4() writeRec5() writeRec6() writeRec7() writeRec8()
def release(self): gribapi.grib_release(self.record)
def writeRec9(): PRES = 1013.0 # Sea level presure (replicate Sara's file) # total accumulated rainfall from past hour (replicate Sara's file) RAIN = 0.0 SC = 0 # snow cover RADSW = 0.0 # SW radiation at surface (replicate Sara's file) RADLW = 0.0 # LW radiation at top (replicate Sara's file) VAPMR = 0.0 # Vagour mixing ratio (replicate Sara's file) for t in range(nfiles): print("Processing file " + filenames[t]) dateTime = parse(date) + dt.timedelta(hours=t * 6) MYR = dateTime.year # Year of data block MMO = dateTime.month # Month of data block MDAY = dateTime.day # Day of data block MHR = dateTime.hour # Hour of data block # GRIB file processing: f = open(filePaths[t], 'r') # Open GRIB file gribapi.grib_multi_support_on() # Turn on multi-message support mcount = gribapi.grib_count_in_file(f) # number of messages in file [gribapi.grib_new_from_file(f) for i in range(mcount)] # Get handles for all messages f.close() # Close GRIB file # Initialse 3D arrays for holding required fields: HGTgrd = np.zeros(shape=(Nj, Ni, NZ)) TMPgrd = np.zeros(shape=(Nj, Ni, NZ)) Ugrd = np.zeros(shape=(Nj, Ni, NZ)) Vgrd = np.zeros(shape=(Nj, Ni, NZ)) Wgrd = np.zeros(shape=(Nj, Ni, NZ)) RHgrd = np.zeros(shape=(Nj, Ni, NZ)) # Loop through included levels and store the values in the appropriate k index of the 3D arrays for k in range(NZ): HGTvals = gribapi.grib_get_values(int(gidHGT[k])) HGTgrd[:, :, k] = np.reshape(HGTvals, (Nj, Ni), 'C') TMPvals = gribapi.grib_get_values(int(gidTMP[k])) TMPgrd[:, :, k] = np.reshape(TMPvals, (Nj, Ni), 'C') Uvals = gribapi.grib_get_values(int(gidU[k])) Ugrd[:, :, k] = np.reshape(Uvals, (Nj, Ni), 'C') Vvals = gribapi.grib_get_values(int(gidV[k])) Vgrd[:, :, k] = np.reshape(Vvals, (Nj, Ni), 'C') Wvals = gribapi.grib_get_values(int(gidW[k])) Wgrd[:, :, k] = np.reshape(Wvals, (Nj, Ni), 'C') RHvals = gribapi.grib_get_values(int(gidRH[k])) RHgrd[:, :, k] = np.reshape(RHvals, (Nj, Ni), 'C') WSgrd = np.sqrt(Ugrd**2 + Vgrd**2) # Calculate wins speed (pythagoras) # Calculate wind direction: # radians, between [-pi,pi], positive anticlockwise from positive x-axis WDgrd = np.arctan2(Vgrd, Ugrd) # degrees, between [-180,180], positive anticlockwise from positive x-axis WDgrd *= 180 / np.pi # degrees, between [0,360], positive anticlockwise from negative x-axis (Since we specify the direction the wind is blowing FROM, not TO) WDgrd += 180 # degrees, between [-360,0], positive clockwise from negative x-axis (Since wind direction is positive clockwise) WDgrd = -WDgrd # degrees, between [-270,90], positive clockwise from positive y-axis (Since wind direction is from North) WDgrd += 90 # degrees, between [0,360], positive clockwise from positive y-axis (DONE!) WDgrd = np.mod(WDgrd, 360) if t > 0: dateTime = parse(date) + dt.timedelta(hours=(t * 6) - 3) print('interpolating') print(dateTime) MYR = dateTime.year # Year of data block MMO = dateTime.month # Month of data block MDAY = dateTime.day # Day of data block MHR = dateTime.hour # Hour of data block HGTgrd = np.mean(np.array([HGTgrd + HGTgrd_ini]), axis=0) TMPgrd = np.mean(np.array([TMPgrd + TMPgrd_ini]), axis=0) Wgrd = np.mean(np.array([Wgrd + Wgrd_ini]), axis=0) RHgrd = np.mean(np.array([RHgrd + RHgrd_ini]), axis=0) WDgrd = np.mean(np.array([WDgrd + WDgrd_ini]), axis=0) WSgrd = np.mean(np.array([WSgrd + WSgrd_ini]), axis=0) inds = HGTgrd.argsort(axis=2) HGTgrd = take_along_axis(HGTgrd, inds, axis=2) TMPgrd = take_along_axis(TMPgrd, inds, axis=2) Wgrd = take_along_axis(Wgrd, inds, axis=2) RHgrd = take_along_axis(RHgrd, inds, axis=2) WSgrd = take_along_axis(WSgrd, inds, axis=2) WDgrd = take_along_axis(WDgrd, inds, axis=2) # Loop over grid cells: for j in range(NY): JX = j + 1 # J-index of grid cell for i in range(NX): IX = i + 1 # i-index of grid cell fout.write( ('{:4d}' + '{:02d}' * 3 + '{:3d}' * 2 + '{:7.1f}{:5.2f}{:2d}' + '{:8.1f}' * 2 + '\n').format( MYR, MMO, MDAY, MHR, IX, JX, PRES, RAIN, SC, RADSW, RADLW)) for k in range(NZ): PRES2 = levsIncl[k] # Pressure (mb) # Elevation (m above sea level) Z = int(HGTgrd[iLatMinGRIB + j, iLonMinGRIB + i, k]) # Temperature (Kelvin) TEMPK = TMPgrd[iLatMinGRIB + j, iLonMinGRIB + i, k] # Wind direction (degrees) WD = int(WDgrd[iLatMinGRIB + j, iLonMinGRIB + i, k]) # Wind speed (m/s) WS = WSgrd[iLatMinGRIB + j, iLonMinGRIB + i, k] # Vertical velocity (m/s) W = Wgrd[iLatMinGRIB + j, iLonMinGRIB + i, k] # Relative humidity (%) RH = int(RHgrd[iLatMinGRIB + j, iLonMinGRIB + i, k]) fout.write(( '{:4d}{:6d}{:6.1f}{:4d}{:5.1f}{:6.2f}{:3d}{:5.2f}\n' ).format(PRES2, Z, TEMPK, WD, WS, W, RH, VAPMR)) # Release all messages: for i in range(mcount): gribapi.grib_release(i + 1) # GRIB file processing: dateTime = parse(date) + dt.timedelta(hours=t * 6) print('processing') print(dateTime) MYR = dateTime.year # Year of data block MMO = dateTime.month # Month of data block MDAY = dateTime.day # Day of data block MHR = dateTime.hour # Hour of data block f = open(filePaths[t], 'r') # Open GRIB file gribapi.grib_multi_support_on() # Turn on multi-message support mcount = gribapi.grib_count_in_file(f) # number of messages in file [gribapi.grib_new_from_file(f) for i in range(mcount)] # Get handles for all messages f.close() # Close GRIB file # Initialse 3D arrays for holding required fields: HGTgrd = np.zeros(shape=(Nj, Ni, NZ)) TMPgrd = np.zeros(shape=(Nj, Ni, NZ)) Ugrd = np.zeros(shape=(Nj, Ni, NZ)) Vgrd = np.zeros(shape=(Nj, Ni, NZ)) Wgrd = np.zeros(shape=(Nj, Ni, NZ)) RHgrd = np.zeros(shape=(Nj, Ni, NZ)) # Loop through included levels and store the values in the appropriate k index of the 3D arrays for k in range(NZ): HGTvals = gribapi.grib_get_values(int(gidHGT[k])) HGTgrd[:, :, k] = np.reshape(HGTvals, (Nj, Ni), 'C') TMPvals = gribapi.grib_get_values(int(gidTMP[k])) TMPgrd[:, :, k] = np.reshape(TMPvals, (Nj, Ni), 'C') Uvals = gribapi.grib_get_values(int(gidU[k])) Ugrd[:, :, k] = np.reshape(Uvals, (Nj, Ni), 'C') Vvals = gribapi.grib_get_values(int(gidV[k])) Vgrd[:, :, k] = np.reshape(Vvals, (Nj, Ni), 'C') Wvals = gribapi.grib_get_values(int(gidW[k])) Wgrd[:, :, k] = np.reshape(Wvals, (Nj, Ni), 'C') RHvals = gribapi.grib_get_values(int(gidRH[k])) RHgrd[:, :, k] = np.reshape(RHvals, (Nj, Ni), 'C') HGTgrd_ini = HGTgrd TMPgrd_ini = TMPgrd Wgrd_ini = Wgrd RHgrd_ini = RHgrd WSgrd = np.sqrt(Ugrd**2 + Vgrd**2) # Calculate wins speed (pythagoras) # Calculate wind direction: # radians, between [-pi,pi], positive anticlockwise from positive x-axis WDgrd = np.arctan2(Vgrd, Ugrd) # degrees, between [-180,180], positive anticlockwise from positive x-axis WDgrd *= 180 / np.pi # degrees, between [0,360], positive anticlockwise from negative x-axis (Since we specify the direction the wind is blowing FROM, not TO) WDgrd += 180 # degrees, between [-360,0], positive clockwise from negative x-axis (Since wind direction is positive clockwise) WDgrd = -WDgrd # degrees, between [-270,90], positive clockwise from positive y-axis (Since wind direction is from North) WDgrd += 90 # degrees, between [0,360], positive clockwise from positive y-axis (DONE!) WDgrd = np.mod(WDgrd, 360) WDgrd_ini = WDgrd WSgrd_ini = WSgrd inds = HGTgrd.argsort(axis=2) HGTgrd = take_along_axis(HGTgrd, inds, axis=2) TMPgrd = take_along_axis(TMPgrd, inds, axis=2) Wgrd = take_along_axis(Wgrd, inds, axis=2) RHgrd = take_along_axis(RHgrd, inds, axis=2) WSgrd = take_along_axis(WSgrd, inds, axis=2) WDgrd = take_along_axis(WDgrd, inds, axis=2) # Loop over grid cells: for j in range(NY): JX = j + 1 # J-index of grid cell for i in range(NX): IX = i + 1 # i-index of grid cell fout.write( ('{:4d}' + '{:02d}' * 3 + '{:3d}' * 2 + '{:7.1f}{:5.2f}{:2d}' + '{:8.1f}' * 2 + '\n').format( MYR, MMO, MDAY, MHR, IX, JX, PRES, RAIN, SC, RADSW, RADLW)) for k in range(NZ): PRES2 = levsIncl[k] # Pressure (mb) # Elevation (m above sea level) Z = int(HGTgrd[iLatMinGRIB + j, iLonMinGRIB + i, k]) # Temperature (Kelvin) TEMPK = TMPgrd[iLatMinGRIB + j, iLonMinGRIB + i, k] # Wind direction (degrees) WD = int(WDgrd[iLatMinGRIB + j, iLonMinGRIB + i, k]) # Wind speed (m/s) WS = WSgrd[iLatMinGRIB + j, iLonMinGRIB + i, k] # Vertical velocity (m/s) W = Wgrd[iLatMinGRIB + j, iLonMinGRIB + i, k] # Relative humidity (%) RH = int(RHgrd[iLatMinGRIB + j, iLonMinGRIB + i, k]) fout.write( ('{:4d}{:6d}{:6.1f}{:4d}{:5.1f}{:6.2f}{:3d}{:5.2f}\n' ).format(PRES2, Z, TEMPK, WD, WS, W, RH, VAPMR)) # Release all messages: for i in range(mcount): gribapi.grib_release(i + 1)
def save(source, target, append=False, sample_file=_sample_file): """ Takes a dataset (source) and writes its contents as grib 1 to file-like target. Grib 1 is used (instead of grib 2) because some older forecast visualization software can't read grib 2. This is a heavily modified but none-the-less derivative of the grib saving functions from the iris package. Parameters ---------- source : Dataset A netcdf-like file holding the dataset we want to write as grib. This must contain time, longitude and latitude coordinates in order to infer the grib grid and time params target : string path or file-like Where the contents should be written. If target is a string the file is created or appended to. append : boolean When creating a new file from string you can optionally append to the file. """ if not _has_gribapi: raise ImportError("gripapi is required to write grib files.") if isinstance(target, basestring): grib_file = open(target, "ab" if append else "wb") elif hasattr(target, "write"): if hasattr(target, "mode") and "b" not in target.mode: raise ValueError("Target not binary") grib_file = target else: raise ValueError("Can only save grib to filename or writable") if not 'latitude' in source.variables or not 'longitude' in source.variables: raise ValueError("Did not find either latitude or longitude.") if source['latitude'].ndim != 1 or source['longitude'].ndim != 1: raise ValueError("Latitude and Longitude should be regular.") if not 'time' in source.variables: raise ValueError("Expected time coordinate") # sort the lats and lons source = source.indexed(latitude=np.argsort(source['latitude'].values)) lons = source['longitude'].values if np.any(np.abs(np.diff(lons)) > 180.): # the latitudes must cross the dateline since we only allow 180 # degree wide bounding boxes, and there is more than a 180 degree # difference between longitudes. Instead we try converting to # 0 to 360 degree longitudes before sorting. lons = np.mod(lons, 360) if np.any(np.abs(np.diff(lons)) > 180.): # TODO: I'm sure theres a way to deal with arbitrary longitude # specifications for global data ... but its not a high priority # so that will wait for later. raise ValueError("Longitudes span more than 180 degrees and the dateline?") source['longitude'].values[:] = lons source = source.indexed(longitude=np.argsort(lons)) # iterate over variables, unless they are considered # auxiliary variables (ie, variables used by slocum # but not in grib files). auxilary_variables = ['wind_speed', 'wind_from_direction'] for single_var in (v for k, v in source.noncoordinates.iteritems() if not k in auxilary_variables): # then iterate over time slices iter_time = (single_var.indexed(**{'time': [i]}) for i in range(single_var.coordinates['time'].size)) for obj in iter_time: # Save this slice to the grib file gribapi.grib_gribex_mode_off() if sample_file is not None and os.path.exists(sample_file): with open(sample_file, 'r') as f: grib_message = gribapi.grib_new_from_file(f) logger.info("Created grib message from file %s" % sample_file) else: logger.info("Creating grib message from gribapi sample: GRIB1") grib_message = gribapi.grib_new_from_samples("GRIB1") set_time(obj, grib_message) set_product(obj, grib_message) set_grid(obj, grib_message) set_data(obj, grib_message) gribapi.grib_write(grib_message, grib_file) gribapi.grib_release(grib_message) # if target was a string then we have to close the file we # created, otherwise leave that up to the user. if isinstance(target, basestring): grib_file.close()
def get_phenomena(self): phen_list = [] phenomenon =\ { "id" : "", "attribute_count" : "", "attributes" :[] } phen_keys = [ "paramId", "cfNameECMF", "cfName", "cfVarName", "units", "nameECMF", "name" ] phen_attr =\ { "name" : "", "value": "" } try: fd = open(self.file_path) while 1: gid = gapi.grib_new_from_file(fd) if gid is None: break phen_attr_list = [] attr_count = 0 for key in phen_keys: if not gapi.grib_is_defined(gid, key): continue value = str(gapi.grib_get(gid, key)) if len(key) < util.MAX_ATTR_LENGTH \ and len(value) < util.MAX_ATTR_LENGTH \ and util.is_valid_phen_attr(value): phen_attr["name"] = str(key.strip()) phen_attr["value"] = str(unicode(value).strip()) if phen_attr not in phen_attr_list: phen_attr_list.append(phen_attr.copy()) attr_count = attr_count + 1 if len(phen_attr_list) > 0: new_phenomenon = phenomenon.copy() new_phenomenon["attributes"] = phen_attr_list new_phenomenon["attribute_count"] = attr_count if new_phenomenon not in phen_list: phen_list.append(new_phenomenon) gapi.grib_release(gid) fd.close() return phen_list except Exception: return None
def get_metadata_level3(self): phen_list = [] phenomenon =\ { "id" : "", "attribute_count" : "", "attributes" :[] } phen_attr =\ { "name" : "", "value": "" } lat_f_l = [] lon_f_l = [] lat_l_l = [] lon_l_l = [] date_d_l = [] date_t_l = [] phen_keys = [ "paramId", "cfNameECMF", "cfName", "cfVarName", "units", "nameECMF", "name", "Ni", "Nj", "latitudeOfFirstGridPointInDegrees", "longitudeOfFirstGridPointInDegrees", "latitudeOfLastGridPointInDegrees", "longitudeOfLastGridPointInDegrees", "dataDate", "dataTime" ] try: fd = open(self.file_path) while 1: gid = gapi.grib_new_from_file(fd) if gid is None: break phen_attr_list = [] attr_count = 0 for key in phen_keys: if not gapi.grib_is_defined(gid, key): continue value = str(gapi.grib_get(gid, key)) #So the file contains many records but all report the #same spatial and temporal information. Only complete distinct records #will be stored i.e the one that contain the full list of parameter #and are unique. If evety record has got different spatial and temporal #then th eindex must change because currently there is only on geo_shape_field. if key == "latitudeOfFirstGridPointInDegrees": lat_f_l.append(value) elif key == "longitudeOfFirstGridPointInDegrees": lon_f_l.append(value) elif key == "latitudeOfLastGridPointInDegrees": lat_l_l.append(value) elif key =="longitudeOfLastGridPointInDegrees": lon_l_l.append(value) elif key == "dataDate": date_d_l.append(value) elif key == "dataTime": date_t_l.append(value) else: if len(key) < util.MAX_ATTR_LENGTH \ and len(value) < util.MAX_ATTR_LENGTH \ and util.is_valid_phen_attr(value): phen_attr["name"] = str(key.strip()) phen_attr["value"] = str(unicode(value).strip()) if phen_attr not in phen_attr_list: phen_attr_list.append(phen_attr.copy()) attr_count = attr_count + 1 if len(phen_attr_list) > 0: new_phenomenon = phenomenon.copy() new_phenomenon["attributes"] = phen_attr_list new_phenomenon["attribute_count"] = attr_count if new_phenomenon not in phen_list: phen_list.append(new_phenomenon) gapi.grib_release(gid) fd.close() if len(lat_f_l) > 0 \ and len(lon_f_l) > 0 \ and len(lat_l_l) > 0 \ and len(lon_l_l) > 0 \ and len(date_d_l) > 0 \ and len(date_t_l): geospatial_dict = {} geospatial_dict["type"] = "envelope" temporal_dict = {} lat_f = min(lat_f_l) lon_f = min(lon_f_l) lat_l = max(lat_l_l) lon_l = max(lon_l_l) date_d = min(date_d_l) date_t = min(date_t_l) if float(lon_l) > 180: lon_l = (float(lon_l) -180) - 180 geospatial_dict["coordinates"] = [[round(float(lon_f), 3), round(float(lat_f), 3)], [round(float(lon_l), 3), round(float(lat_l), 3) ]] temporal_dict["start_time"] = date_d temporal_dict["end_time"] = date_t return (phen_list, geospatial_dict, temporal_dict) else: return (phen_list,) except Exception as ex: return None
def merge_cur_months(month, fin1, fin2, fouts, writer): gidinst, gidcum = -1, -1 timinst, timcum = -1, -1 procinst, proccum = True, True instmode = False while True: if (instmode): if (procinst): if (gidinst != -1): gribapi.grib_release(gidinst) gidinst = gribapi.grib_new_from_file(fin1) if (not gidinst): break time = int(gribapi.grib_get(gidinst, "dataTime")) if (timinst == -1): timinst = time if (time != timinst): timinst = time procinst = False instmode = False continue else: procinst = True code = make_grib_tuple(gribapi.grib_get(gidinst, "param")) if (code in accum_codes): continue date = int(gribapi.grib_get(gidinst, "dataDate")) mon = (date % 10**4) / 10**2 if (mon == month): fix_Pa_pressure_levels(gidinst) writer(gidinst, fouts) else: if (proccum): if (gidinst != -1): gribapi.grib_release(gidcum) gidcum = gribapi.grib_new_from_file(fin2) if (not gidcum): procinst = False instmode = True continue time = int(gribapi.grib_get(gidcum, "dataTime")) if (timcum == -1): timcum = time if (time != timcum): timcum = time proccum = False instmode = True continue else: proccum = True code = make_grib_tuple(gribapi.grib_get(gidcum, "param")) if (code not in accum_codes): continue if (timeshift > 0): date = int(gribapi.grib_get(gidcum, "dataDate")) mon = (date % 10**4) / 10**2 newdate = date newtime = time - 100 * timeshift if (newtime < 0): curdate = datetime.date(date / 10**4, mon, date % 10**2) prevdate = curdate - datetime.timedelta(days=1) mon = prevdate.month newdate = prevdate.year * 10**4 + mon * 10**2 + prevdate.day newtime = 2400 + newtime gribapi.grib_set(gidcum, "dataDate", newdate) gribapi.grib_set(gidcum, "dataTime", newtime) if (mon == month): fix_Pa_pressure_levels(gidcum) writer(gidcum, fouts)