docs: def to_mesh(obj):
      '''
      to_mesh(obj) yields a Mesh object that is equivalent to obj or identical to obj if obj is itself
        a mesh object.
  
      The following objects can be converted into meshes:
        * a mesh object
        * a tuple (coords, faces) where coords is a coordinate matrix and faces is a matrix of
          coordinate indices that make-up the triangles
        * a tuple (faces, coords) where faces is a triangle matrix and coords is a coordinate matrix;
          note that if neither matrix is of integer type, then the latter ordering (which is the same
          as that accepted by the mesh() function) is assumed.
        * a tuple (topo, regname) specifying the registration name to use (note that regname may
          optionally start with 'reg:' which is ignored).
        * a tuple (cortex, surfname) specifying the surface name to use. Note that surfname may
          optionally start with 'surf:' or 'reg:', both of which are used only to determine whether
          to lookup a registration or a surface. If no 'surf:' or 'reg:' is given as a prefix, then
          a surface is tried first followed by a registration. The surface name 'sphere' is
          automatically translated to 'reg:native' and any surface name of the form '<name>_sphere' is
          automatically translated to 'reg:<name>'.
        * a tuple (topo/cortex, mesh) results in the mesh being returned.
        * a tuple (mesh, string) or (mesh, None) results in mesh with the second argument ignored.
        * a tuple (mesh1, mesh2) results in mesh2 with mesh1 ignored.
  
      Note that some of the behavior described above is desirable because of a common use case of the
      to_mesh function. When another function f accepts as arguments both a hemi/topology object as
      well as an optional surface argument, the purpose is often to obtain a specific mesh from the
      topology but to allow the user to specify which or to pass their own mesh.
      '''
      if   is_mesh(obj): return obj
      elif pimms.is_vector(obj) and len(obj) == 2:
          (a,b) = obj
          if   pimms.is_matrix(a, 'int') and pimms.is_matrix(b, 'real'): return mesh(a, b)
          elif pimms.is_matrix(b, 'int') and pimms.is_matrix(a, 'real'): return mesh(b, a)
          elif is_mesh(a) and (b is None or pimms.is_str(b)): return a
          elif is_mesh(a) and is_mesh(b): return b
          elif is_topo(a):
              from neuropythy import is_cortex
              if   is_mesh(b):          return b
              elif not pimms.is_str(b): raise ValueError('to_mesh: non-str surf/reg name: %s' % (b,))
              (b0, lb) = (b, b.lower())
              # check for translations of the name first:
              s = b[4:] if lb.startswith('reg:') else b[5:] if lb.startswith('surf:') else b
              ls = s.lower()
              if ls.endswith('_sphere'): b = ('reg:' + s[:-7])
              elif ls == 'sphere': b = 'reg:native'
              lb = b.lower()
              # we try surfaces first (if a is a cortex and has surfaces)
              if is_cortex(a) and not lb.startswith('reg:'):
                  (s,ls) = (b[5:],lb[5:]) if lb.startswith('surf:') else (b,lb)
                  if   s  in a.surfaces: return a.surfaces[s]
                  elif ls in a.surfaces: return a.surfaces[ls]
              # then check registrations
              if not lb.startswith('surf:'):
                  (s,ls) = (b[4:],lb[4:]) if lb.startswith('reg:') else (b,lb)
                  if   s  in a.registrations: return a.registrations[s]
                  elif ls in a.registrations: return a.registrations[ls]
              # nothing found
              raise ValueError('to_mesh: mesh named "%s" not found in topology %s' % (b0, a))
          else: raise ValueError('to_mesh: could not deduce meaning of row: %s' % (obj,))
      else: raise ValueError('Could not deduce how object can be convertex into a mesh')