<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def ransohoff_snap_off(target, shape_factor=2.0, wavelength=5e-6, require_pair=False, surface_tension='pore.surface_tension', contact_angle='pore.contact_angle', diameter='throat.diameter', vertices='throat.offset_vertices', **kwargs):
 r""" Computes the capillary snap-off pressure assuming the throat is cylindrical with converging-diverging change in diamater - like the Purcell model. The wavelength of the change in diamater is the fiber radius. Parameters target : OpenPNM Object The object for which these values are being calculated. This controls the length of the calculated array, and also provides access to other necessary thermofluid properties. shape_factor : constant dependent on the shape of throat cross-section 1.75 - 2.0, see Ref wavelength : float or array like The transverse interfacial radius of curvature at the neck (fiber radius in fibrous media) require_pair : bool Controls whether snap-off requires a pair of arc meniscii to occur. surface_tension : dict key (string) The dictionary key containing the surface tension values to be used. If a pore property is given, it is interpolated to a throat list. contact_angle : dict key (string) The dictionary key containing the contact angle values to be used. If a pore property is given, it is interpolated to a throat list. throat_diameter : dict key (string) The dictionary key containing the throat diameter values to be used. Notes ----- This equation should be used to calculate the snap off capillary pressure in fribrous media References [1]: Ransohoff, T.C., Gauglitz, P.A. and Radke, C.J., 1987. Snap‐off of gas bubbles in smoothly constricted noncircular capillaries. AIChE Journal, 33(5), pp.753-765. """

    phase = target.project.find_phase(target)
    geometry = target.project.find_geometry(target)
    element, sigma, theta = _get_key_props(phase=phase,
                                           diameter=diameter,
                                           surface_tension=surface_tension,
                                           contact_angle=contact_angle)
    try:
        all_verts = geometry[vertices]
        # Work out whether throat geometry can support at least one pair of
        # adjacent arc menisci that can grow and merge to form snap-off
        # Only works if throat vertices are in convex hull order
        angles_ok = np.zeros(geometry.Nt, dtype=bool)
        for T in range(geometry.Nt):
            verts = all_verts[T]
            x = verts[:, 0]
            y = verts[:, 1]
            z = verts[:, 2]
            # PLus
            p = 1
            # Minus
            m = -1
            verts_p = np.vstack((np.roll(x, p),
                                 np.roll(y, p),
                                 np.roll(z, p))).T
            verts_m = np.vstack((np.roll(x, m),
                                 np.roll(y, m),
                                 np.roll(z, m))).T
            v1 = verts_p - verts
            v2 = verts_m - verts
            corner_angles = np.rad2deg(tr.angle_between_vectors(v1,
                                                                v2,
                                                                axis=1))
            # Logical test for existence of arc menisci
            am = theta[T] <= 90 - corner_angles/2
            if require_pair:
                # Logical test for two adjacent arc menisci
                pair_p = np.logical_and(am, np.roll(am, + p))
                pair_m = np.logical_and(am, np.roll(am, + m))
                am_pair = np.any(np.logical_or(pair_p, pair_m))
                angles_ok[T] = am_pair
            else:
                # Logical test for any arc menisci
                angles_ok[T] = np.any(am)
    except:
        logger.warning("Model is designed to work with property: " +
                       vertices)
        angles_ok = np.ones(geometry.Nt, dtype=bool)

    # Condition for arc menisci to form in corners
    rad_Ts = geometry[diameter]/2
    # Ransohoff and Radke eq. 4
    C = 1/rad_Ts - 1/wavelength
    value = sigma[phase.throats(target.name)]*C
    # Only throats that can support arc menisci can snap-off
    value[~angles_ok] = np.nan
    logger.info("Snap off pressures calculated for " +
                str(np.around(100*np.sum(angles_ok)/np.size(angles_ok), 0)) +
                "% of throats")
    return value