예제 #1
0
파일: __init__.py 프로젝트: nkeane/PyFerret
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()
예제 #2
0
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
예제 #3
0
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