code: def proc_file(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
  
file_path: nibabel/nibabel/cmdline/ls.py
imports: import sys
  from optparse import Option, OptionParser
  import numpy
  import nibabel
  import nibabel.cmdline.utils
  from nibabel.cmdline.utils import _err, ap, safe_get, table2string, verbose
label_desc: Use image node_id 2 for calling a global function with example usage: proc_file(f, opts) and returns: row, row