@with_connection<EOL>def find_frametype(channel, gpstime=None, frametype_match=None,<EOL>host=None, port=None, return_all=False, allow_tape=False,<EOL>connection=None, on_gaps='<STR_LIT:error>'):
<EOL>from ..detector import Channel<EOL>if isinstance(channel, (list, tuple)):<EOL><INDENT>channels = channel<EOL><DEDENT>else:<EOL><INDENT>channels = [channel]<EOL><DEDENT>chans = {Channel(c).name: c for c in channels}<EOL>names = set(chans.keys())<EOL>if isinstance(gpstime, (list, tuple)):<EOL><INDENT>from ..segments import Segment<EOL>gpssegment = Segment(*gpstime)<EOL>gpstime = gpssegment[<NUM_LIT:0>]<EOL><DEDENT>else:<EOL><INDENT>gpssegment = None<EOL><DEDENT>if gpstime is not None:<EOL><INDENT>gpstime = int(to_gps(gpstime))<EOL><DEDENT>if frametype_match is None and gpstime is not None and gpstime > <NUM_LIT>:<EOL><INDENT>frametype_match = GRB_TYPE<EOL><DEDENT>match = {}<EOL>ifos = set()  <EOL>while names:<EOL><INDENT>try:<EOL><INDENT>name = next(iter(names))<EOL><DEDENT>except KeyError:<EOL><INDENT>break<EOL><DEDENT>else:<EOL><INDENT>chan = Channel(chans[name])<EOL><DEDENT>try:<EOL><INDENT>ifo = chan.ifo[<NUM_LIT:0>]<EOL><DEDENT>except TypeError:  <EOL><INDENT>raise ValueError("<STR_LIT>"<EOL>"<STR_LIT>" % str(chan))<EOL><DEDENT>if ifo in ifos:<EOL><INDENT>names.pop()<EOL>continue<EOL><DEDENT>ifos.add(ifo)<EOL>types = find_types(ifo, match=frametype_match, trend=chan.type,<EOL>connection=connection)<EOL>for ftype in types:<EOL><INDENT>try:<EOL><INDENT>path = find_latest(ifo, ftype, gpstime=gpstime,<EOL>allow_tape=allow_tape,<EOL>connection=connection, on_missing='<STR_LIT:ignore>')<EOL><DEDENT>except (RuntimeError, IOError, IndexError):  <EOL><INDENT>continue<EOL><DEDENT>if gpssegment is None:<EOL><INDENT>gaps = <NUM_LIT:0><EOL><DEDENT>else:<EOL><INDENT>cache = find_urls(ifo, ftype, *gpssegment, on_gaps=on_gaps,<EOL>connection=connection)<EOL>csegs = cache_segments(cache)<EOL>gaps = abs(gpssegment) - abs(csegs)<EOL><DEDENT>i = <NUM_LIT:0><EOL>nchan = len(names)<EOL>for n in iter_channel_names(path):<EOL><INDENT>if n in names:<EOL><INDENT>i += <NUM_LIT:1><EOL>c = chans[n]  <EOL>try:<EOL><INDENT>match[c].append((ftype, path, -gaps))<EOL><DEDENT>except KeyError:<EOL><INDENT>match[c] = [(ftype, path, -gaps)]<EOL><DEDENT>if not return_all:  <EOL><INDENT>names.remove(n)<EOL><DEDENT>if not names or n == nchan:  <EOL><INDENT>break<EOL><DEDENT><DEDENT><DEDENT>if not names:  <EOL><INDENT>break<EOL><DEDENT><DEDENT>try:<EOL><INDENT>names.pop()<EOL><DEDENT>except KeyError:  <EOL><INDENT>break<EOL><DEDENT><DEDENT>missing = set(channels) - set(match.keys())<EOL>if missing:<EOL><INDENT>msg = "<STR_LIT>"<EOL>if gpstime:<EOL><INDENT>msg += "<STR_LIT>" % gpstime<EOL><DEDENT>msg += "<STR_LIT>".format('<STR_LIT>'.join(missing))<EOL>if not allow_tape:<EOL><INDENT>msg += ("<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>raise ValueError(msg)<EOL><DEDENT>if return_all:<EOL><INDENT>paths = set(p[<NUM_LIT:1>] for key in match for p in match[key])<EOL>rank = {path: (on_tape(path), num_channels(path)) for path in paths}<EOL>for key in match:<EOL><INDENT>match[key].sort(key=lambda x: (x[<NUM_LIT:2>],) + rank[x[<NUM_LIT:1>]])<EOL><DEDENT>ftypes = {key: list(list(zip(*match[key]))[<NUM_LIT:0>]) for key in match}<EOL><DEDENT>else:<EOL><INDENT>ftypes = {key: match[key][<NUM_LIT:0>][<NUM_LIT:0>] for key in match}<EOL><DEDENT>if isinstance(channel, (list, tuple)):<EOL><INDENT>return ftypes<EOL><DEDENT>return ftypes[str(channel)]<EOL>
Find the frametype(s) that hold data for a given channel

    Parameters
    ----------
    channel : `str`, `~gwpy.detector.Channel`
        the channel to be found

    gpstime : `int`, optional
        target GPS time at which to find correct type

    frametype_match : `str`, optional
        regular expression to use for frametype `str` matching

    host : `str`, optional
        name of datafind host to use

    port : `int`, optional
        port on datafind host to use

    return_all : `bool`, optional, default: `False`
        return all found types, default is to return to 'best' match

    allow_tape : `bool`, optional, default: `False`
        do not test types whose frame files are stored on tape (not on
        spinning disk)

    on_gaps : `str`, optional
        action to take when gaps are discovered in datafind coverage,
        default: ``'error'``, i.e. don't match frametypes with gaps.
        Select ``'ignore'`` to ignore gaps, or ``'warn'`` to display
        warnings when gaps are found in a datafind `find_urls` query

    Returns
    -------
    If a single name is given, and `return_all=False` (default):

    frametype : `str`
        name of best match frame type

    If a single name is given, and `return_all=True`:

    types : `list` of `str`
        the list of all matching frame types

    If multiple names are given, the above return types are wrapped into a
    `dict` of `(channel, type_or_list)` pairs.

    Examples
    --------
    >>> from gwpy.io import datafind as io_datafind
    >>> io_datafind.find_frametype('H1:IMC-PWR_IN_OUTPUT', gpstime=1126259462)
    'H1_R'
    >>> io_datafind.find_frametype('H1:IMC-PWR_IN_OUTPUT', gpstime=1126259462,
    ...                            return_all=True)
    ['H1_R', 'H1_C']
    >>> io_datafind.find_frametype(
    ...     ('H1:IMC-PWR_IN_OUTPUT', 'H1:OMC-DCPD_SUM_OUTPUT',
    ...      'H1:GDS-CALIB_STRAIN'),
    ...     gpstime=1126259462, return_all=True))"
    {'H1:GDS-CALIB_STRAIN': ['H1_HOFT_C00'],
     'H1:OMC-DCPD_SUM_OUTPUT': ['H1_R', 'H1_C'],
     'H1:IMC-PWR_IN_OUTPUT': ['H1_R', 'H1_C']}