Ejemplo n.º 1
0
def ferret_result_limits(efid):
    """
    Abstract axis limits for the shapefile_readxyz PyEF
    """
    maxpts = pyferret.get_arg_one_val(efid, pyferret.ARG2)
    maxpts = int(maxpts)
    if maxpts == -1:
        shapefile_name = pyferret.get_arg_one_val(efid, pyferret.ARG1)
        sf = shapefile.Reader(shapefile_name)
        maxpts = 0
        for shp in sf.shapes():
            maxpts += len(shp.points) + 1
    elif maxpts < 1:
        raise ValueError("MAXPTS must be a positive integer or -1")
    return ( (1, maxpts), (1, 3), None, None, None, None, )
Ejemplo n.º 2
0
def ferret_result_limits(efid):
    '''
    Provides the bounds of the E abstract axis.  
    The maximum number of EOFs is the number of locations. 
    '''
    maxeofs = pyferret.get_arg_one_val(efid, pyferret.ARG3)
    if maxeofs > 0.95:
        maxeofs = int(maxeofs + 0.1)
    else:
        maxeofs = 1
        for axis in (pyferret.X_AXIS, pyferret.Y_AXIS, pyferret.Z_AXIS):
            axis_info = pyferret.get_axis_info(efid, pyferret.ARG1, axis)
            if axis_info:
                npts = axis_info.get("size", -1)
                if npts > 0:
                    maxeofs *= npts
    result_limits = [None] * pyferret.MAX_FERRET_NDIM
    result_limits[pyferret.E_AXIS] = (1, maxeofs + 1)
    return result_limits
Ejemplo n.º 3
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
Ejemplo n.º 4
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