def stop(): """ Runs a series of Ferret commands to return Ferret to its default state, then shuts down and releases all memory used by Ferret. After calling this function do not call any Ferret functions except start, which will restart Ferret and re-enable the other functions. Returns: False if Ferret has not been started or has already been stopped True otherwise """ # If it had been started, shut down ESMP and delete the log file try: regrid.ESMPControl().stopESMP(True) except Exception: pass # clear "the" anonymous dataset pyferret.anondset.close() # Continue with Ferret shutdown return libpyferret._stop()
def ferret_compute(efid, result, result_bdf, inputs, input_bdfs): ''' Performs the regridding for the curv2rect function. Arguments: result - numpy array for rectilinear data values to be assigned result_bdf - numpy array of the missing-data value for result inputs - numpy arrays (CurvData, CurvCenterLons, CurvCenterLats, CurvCornerLons, CurvCornerLats. TemplateRectVar, Method) input_bdfs - numpy arrays of missing-data values for the corresponding inputs array ''' # Get the regridding method to use methodstr = pyferret.get_arg_one_val(efid, pyferret.ARG7).upper() if methodstr == "BILINEAR": method = ESMP.ESMP_REGRIDMETHOD_BILINEAR elif methodstr == "PATCH": method = ESMP.ESMP_REGRIDMETHOD_PATCH elif methodstr == "CONSERVE": method = ESMP.ESMP_REGRIDMETHOD_CONSERVE else: raise ValueError("Unknown method %s" % methodstr) # Get the template data and missing value template_data = inputs[pyferret.ARG6] template_undef = input_bdfs[pyferret.ARG6] # Get the rectilinear center longitudes and latitudes rect_center_lons = pyferret.get_axis_coordinates(efid, pyferret.ARG6, pyferret.X_AXIS) rect_center_lats = pyferret.get_axis_coordinates(efid, pyferret.ARG6, pyferret.Y_AXIS) # Get the rectilinear corner longitudes lo, hi = pyferret.get_axis_box_limits(efid, pyferret.ARG6, pyferret.X_AXIS) if not numpy.allclose(lo[1:], hi[:-1]): raise ValueError("Unexpected ARG6 X_AXIS box limit values " \ "returned from pyferret.get_axis_box_limits") rect_corner_lons = numpy.empty((lo.shape[0] + 1), dtype=numpy.float64) rect_corner_lons[0] = lo[0] rect_corner_lons[1:] = hi # Get the rectilinear corner latitudes lo, hi = pyferret.get_axis_box_limits(efid, pyferret.ARG6, pyferret.Y_AXIS) if not numpy.allclose(lo[1:], hi[:-1]): raise ValueError("Unexpected ARG6 Y_AXIS box limit values " \ "returned from pyferret.get_axis_box_limits") rect_corner_lats = numpy.empty((lo.shape[0] + 1), dtype=numpy.float64) rect_corner_lats[0] = lo[0] rect_corner_lats[1:] = hi # Get the curvilinear data curv_data = inputs[pyferret.ARG1] curv_centers_shape = (curv_data.shape[0], curv_data.shape[1]) if (curv_data.shape[2:] != template_data.shape[2:]): raise ValueError("Curvilinear data and template variable " \ "must have same Z, T, E, and F axes") curv_undef = input_bdfs[pyferret.ARG1] # Get the curvilinear centers arrays lons = inputs[pyferret.ARG2].squeeze() lats = inputs[pyferret.ARG3].squeeze() if (lons.shape == curv_centers_shape) and (lats.shape == curv_centers_shape): curv_center_lons = lons curv_center_lats = lats elif (lons.shape == ()) and (lats.shape == ()): curv_center_lons = None curv_center_lats = None else: raise ValueError("Curvilinear center points must have " \ "appropriate shape or be singletons") # Get the curvilinear corners arrays lons = inputs[pyferret.ARG4].squeeze() lats = inputs[pyferret.ARG5].squeeze() corners_shape = (curv_data.shape[0] + 1, curv_data.shape[1] + 1) corners_shape_3d = (curv_data.shape[0], curv_data.shape[1], 4) if (lons.shape == corners_shape) and (lats.shape == corners_shape): curv_corner_lons = lons curv_corner_lats = lats elif (lons.shape == corners_shape_3d) and (lats.shape == corners_shape_3d): curv_corner_lons, curv_corner_lats = regrid.quadCornersFrom3D( lons, lats) elif method == ESMP.ESMP_REGRIDMETHOD_CONSERVE: raise ValueError("CONSERVE method requires " \ "curvilinear grid corner coordinates") elif (lons.shape == ()) and (lats.shape == ()): curv_corner_lons = None curv_corner_lats = None else: raise ValueError("Curvilinear corner points must have " \ "appropriate shape or be singletons") # If curvilinear center point coordinates not given, # generate them from the curvilinear corner points if curv_center_lons is None: if not curv_corner_lons is None: curv_center_lons, curv_center_lats = \ regrid.quadCentroids(curv_corner_lons, curv_corner_lats) else: raise ValueError("Valid center or corner curvilinear " \ "grid coordinates must be given") # Make sure ESMP is, or has been, initialized regrid.ESMPControl().startCheckESMP() # Create the regridder used repeatedly in this function regridder = regrid.CurvRectRegridder() last_curv_center_ignore = None last_rect_center_ignore = None # Increment the depth index last # most likely to change the undefined (e.g., land) mask for d_idx in range(curv_data.shape[2]): # Arrays are probably in Fortran order, so increment last indices last for f_idx in range(curv_data.shape[5]): for e_idx in range(curv_data.shape[4]): for t_idx in range(curv_data.shape[3]): # Determine curvilinear center points to ignore from undefined data curv_center_ignore = ( numpy.abs(curv_data[:, :, d_idx, t_idx, e_idx, f_idx] - curv_undef) < 1.0E-7) # If mask has changed, need to recreate the curvilinear grid if (last_curv_center_ignore is None) or \ numpy.any(curv_center_ignore != last_curv_center_ignore): regridder.createCurvGrid(curv_center_lons, curv_center_lats, curv_center_ignore, curv_corner_lons, curv_corner_lats, None) last_curv_center_ignore = curv_center_ignore # Determine rectilinear center points to ignore from undefined data rect_center_ignore = (numpy.abs( template_data[:, :, d_idx, t_idx, e_idx, f_idx] - template_undef) < 1.0E-7) # If mask has changed, need to recreate the rectilinear grid if (last_rect_center_ignore is None) or \ numpy.any(rect_center_ignore != last_rect_center_ignore): regridder.createRectGrid(rect_center_lons, rect_center_lats, rect_center_ignore, rect_corner_lons, rect_corner_lats, None) last_rect_center_ignore = rect_center_ignore # Assign the curvilinear data regridder.assignCurvField(curv_data[:, :, d_idx, t_idx, e_idx, f_idx]) # Allocate space for the rectilinear data from the regridding regridder.assignRectField(None) # Regrid and assign the rectilinear data to the results array regrid_data = regridder.regridCurvToRect( result_bdf, method) result[:, :, d_idx, t_idx, e_idx, f_idx] = regrid_data return
def ferret_compute(efid, result, result_bdf, inputs, input_bdfs): ''' Performs the regridding for the curv3srect function. Arguments: result - rectilinear data values to be assigned result_bdf - missing-data value for result inputs - (CurvData, CurvLons, CurvLats, CurvBaths, CurvZetas, TemplateRectVar, Method) input_bdfs - missing-data values for the corresponding inputs array ''' # Get the regridding method to use methodstr = pyferret.get_arg_one_val(efid, pyferret.ARG7).upper() if methodstr == "BILINEAR": method = ESMP.ESMP_REGRIDMETHOD_BILINEAR elif methodstr == "PATCH": method = ESMP.ESMP_REGRIDMETHOD_PATCH else: raise ValueError("Unknown method %s (CONSERVE not supported)" % methodstr) # Get the template data and missing value template_data = inputs[pyferret.ARG6] template_undef = input_bdfs[pyferret.ARG6] # Get the rectilinear center longitudes, latitudes, and depths rect_center_lons = pyferret.get_axis_coordinates(efid, pyferret.ARG6, pyferret.X_AXIS) rect_center_lats = pyferret.get_axis_coordinates(efid, pyferret.ARG6, pyferret.Y_AXIS) rect_center_depths = pyferret.get_axis_coordinates(efid, pyferret.ARG6, pyferret.Z_AXIS) # Get the rectilinear corner longitudes lo, hi = pyferret.get_axis_box_limits(efid, pyferret.ARG6, pyferret.X_AXIS) if not numpy.allclose(lo[1:], hi[:-1]): raise ValueError("Unexpected ARG6 X_AXIS box limit values " \ "returned from pyferret.get_axis_box_limits") rect_corner_lons = numpy.empty((lo.shape[0] + 1), dtype=numpy.float64) rect_corner_lons[0] = lo[0] rect_corner_lons[1:] = hi # Get the rectilinear corner latitudes lo, hi = pyferret.get_axis_box_limits(efid, pyferret.ARG6, pyferret.Y_AXIS) if not numpy.allclose(lo[1:], hi[:-1]): raise ValueError("Unexpected ARG6 Y_AXIS box limit values " \ "returned from pyferret.get_axis_box_limits") rect_corner_lats = numpy.empty((lo.shape[0] + 1), dtype=numpy.float64) rect_corner_lats[0] = lo[0] rect_corner_lats[1:] = hi # Get the rectilinear corner depths lo, hi = pyferret.get_axis_box_limits(efid, pyferret.ARG6, pyferret.Z_AXIS) if not numpy.allclose(lo[1:], hi[:-1]): raise ValueError("Unexpected ARG6 Z_AXIS box limit values " \ "returned from pyferret.get_axis_box_limits") rect_corner_depths = numpy.empty((lo.shape[0] + 1), dtype=numpy.float64) rect_corner_depths[0] = lo[0] rect_corner_depths[1:] = hi # Get the curvilinear data curv_data = inputs[pyferret.ARG1] if curv_data.shape[3:] != template_data.shape[3:]: raise ValueError("Curvilinear data and template variable " \ "must have same T, E, and F axes") curv_undef = input_bdfs[pyferret.ARG1] # Get the curvilinear centers arrays - squeeze removes the singleton axes curv_center_lons = inputs[pyferret.ARG2].squeeze() curv_center_lats = inputs[pyferret.ARG3].squeeze() curv_center_baths = inputs[pyferret.ARG4].squeeze() curv_centers_shape = curv_data.shape[:2] if (curv_center_lons.shape != curv_centers_shape) or \ (curv_center_lats.shape != curv_centers_shape) or \ (curv_center_baths.shape != curv_centers_shape): raise ValueError("Curvilinear data, longitude, latitudes, and " \ "and bathymetry must have same X and Y axes") # Squeeze should remove a singleton Z axis in zetas curv_center_zetas = inputs[pyferret.ARG5].squeeze() # If only one time step, squeeze would have also removed it. # So if no time axis, put one in. if len(curv_center_zetas.shape) == 2: curv_center_zetas = curv_center_zetas[:, :, numpy.newaxis] # Allow zeta to be omitted by giving a single-point array if curv_center_zetas.shape == (): curv_center_zetas = None elif curv_center_zetas.shape != (curv_data.shape[0], curv_data.shape[1], curv_data.shape[3]): raise ValueError("Curvilinear data and zetas " \ "must have same X, Y, and T axes") # Get the sigma values from the Z axis of curv_data curv_center_sigmas = pyferret.get_axis_coordinates(efid, pyferret.ARG1, pyferret.Z_AXIS) curv_centers_shape = curv_data.shape[:3] # Expand the sigmas to 3D (adding X and Y axes) to simplify # calculation of curvilinear depths curv_center_sigmas = numpy.repeat(curv_center_sigmas, curv_centers_shape[0] * \ curv_centers_shape[1]) \ .reshape(curv_centers_shape, order='F') # Expand the curvilinear longitude, latitude, and bathymetry # arrays to 3D (adding Z axis) curv_center_lons = numpy.tile(curv_center_lons.flatten('F'), curv_centers_shape[2]) \ .reshape(curv_centers_shape, order='F') curv_center_lats = numpy.tile(curv_center_lats.flatten('F'), curv_centers_shape[2]) \ .reshape(curv_centers_shape, order='F') curv_center_baths = numpy.tile(curv_center_baths.flatten('F'), curv_centers_shape[2]) \ .reshape(curv_centers_shape, order='F') # Make sure ESMP is, or has been, initialized regrid.ESMPControl().startCheckESMP() # Create the regridder used repeatedly in this function regridder3d = regrid.CurvRect3DRegridder() last_rect_center_ignore = None if curv_center_zetas == None: # Create the curvilinear depths array curv_center_depths = curv_center_sigmas * curv_center_baths last_curv_center_ignore = None # Increment the time index last since zeta is time dependent for t_idx in range(curv_data.shape[3]): if curv_center_zetas != None: # Expand the zetas for this time step to 3D - adding Z axis zetas = numpy.tile(curv_center_zetas[:,:,t_idx].flatten('F'), curv_centers_shape[2]) \ .reshape(curv_centers_shape, order='F') # Create the curvilinear depths array curv_center_depths = curv_center_sigmas * (curv_center_baths + \ zetas) - zetas # Different curvilinear depths, so need to recreate the curvilinear grid last_curv_center_ignore = None # Arrays are probably in Fortran order, so increment last indices last for f_idx in range(curv_data.shape[5]): for e_idx in range(curv_data.shape[4]): # Determine curvilinear center points to ignore from undefined data curv_center_ignore = ( numpy.abs(curv_data[:, :, :, t_idx, e_idx, f_idx] - curv_undef) < 1.0E-7) # If mask has changed, need to recreate the curvilinear grid if (last_curv_center_ignore is None) or \ numpy.any(curv_center_ignore != last_curv_center_ignore): regridder3d.createCurvGrid(curv_center_lons, curv_center_lats, curv_center_depths, curv_center_ignore, True, None, None, None, None) last_curv_center_ignore = curv_center_ignore # Determine rectilinear center points to ignore from undefined data rect_center_ignore = ( numpy.abs(template_data[:, :, :, t_idx, e_idx, f_idx] - template_undef) < 1.0E-7) # If mask has changed, need to recreate the rectilinear grid if (last_rect_center_ignore is None) or \ numpy.any(rect_center_ignore != last_rect_center_ignore): regridder3d.createRectGrid( rect_center_lons, rect_center_lats, rect_center_depths, rect_center_ignore, True, rect_corner_lons, rect_corner_lats, rect_corner_depths, None) last_rect_center_ignore = rect_center_ignore # Assign the curvilinear data regridder3d.assignCurvField(curv_data[:, :, :, t_idx, e_idx, f_idx]) # Allocate space for the rectilinear data from the regridding regridder3d.assignRectField(None) # Regrid and assign the rectilinear data to the results array regrid_data = regridder3d.regridCurvToRect(result_bdf, method) result[:, :, :, t_idx, e_idx, f_idx] = regrid_data return