def METHOD_NAME(f, opts):
    verbose(1, f'Loading {f}')
    row = [f'@l{f}']
    try:
        vol = nib.load(f)
        h = vol.header
    except Exception as e:
        row += ['failed']
        verbose(2, f'Failed to gather information -- {e}')
        return row
    row += [
        str(safe_get(h, 'data_dtype')),
        f"@l[{ap(safe_get(h, 'data_shape'), '%3g')}]",
        f"@l{ap(safe_get(h, 'zooms'), '%.2f', 'x')}",
    ]
    # Slope
    if (
        hasattr(h, 'has_data_slope')
        and (h.has_data_slope or h.has_data_intercept)
        and not h.get_slope_inter() in [(1.0, 0.0), (None, None)]
    ):
        row += ['@l*%.3g+%.3g' % h.get_slope_inter()]
    else:
        row += ['']
    if hasattr(h, 'extensions') and len(h.extensions):
        row += ['@l#exts: %d' % len(h.extensions)]
    else:
        row += ['']
    if opts.header_fields:
        # signals "all fields"
        if opts.header_fields == 'all':
            # TODO: might vary across file types, thus prior sensing
            # would be needed
            header_fields = h.keys()
        else:
            header_fields = opts.header_fields.split(',')
        for f in header_fields:
            if not f:  # skip empty
                continue
            try:
                row += [str(h[f])]
            except (KeyError, ValueError):
                row += [_err()]
    try:
        if (
            hasattr(h, 'get_qform')
            and hasattr(h, 'get_sform')
            and (h.get_qform() != h.get_sform()).any()
        ):
            row += ['sform']
        else:
            row += ['']
    except Exception as e:
        verbose(2, f'Failed to obtain qform or sform -- {e}')
        if isinstance(h, nib.AnalyzeHeader):
            row += ['']
        else:
            row += [_err()]
    if opts.stats or opts.counts:
        # We are doomed to load data
        try:
            d = np.asarray(vol.dataobj)
            if not opts.stats_zeros:
                d = d[np.nonzero(d)]
            else:
                # at least flatten it -- functionality below doesn't
                # depend on the original shape, so let's use a flat view
                d = d.reshape(-1)
            if opts.stats:
                # just # of elements
                row += ['@l[%d]' % np.prod(d.shape)]
                # stats
                row += [f'@l[{np.min(d):.2g}, {np.max(d):.2g}]' if len(d) else '-']
            if opts.counts:
                items, inv = np.unique(d, return_inverse=True)
                if len(items) > 1000 and not opts.all_counts:
                    counts = _err('%d uniques. Use --all-counts' % len(items))
                else:
                    freq = np.bincount(inv)
                    counts = ' '.join('%g:%d' % (i, f) for i, f in zip(items, freq))
                row += ['@l' + counts]
        except OSError as e:
            verbose(2, f'Failed to obtain stats/counts -- {e}')
            row += [_err()]
    return row