code: def gather_categories(imap, header, categories=None):
      if categories is None:
          return {"default": DataCategory(set(imap.keys()), {})}
      cat_ids = [header.index(cat)
                 for cat in categories if cat in header and "=" not in cat]
      table = OrderedDict()
      conditions = defaultdict(set)
      for i, cat in enumerate(categories):
          if "=" in cat and cat.split("=")[0] in header:
              cat_name = header[header.index(cat.split("=")[0])]
              conditions[cat_name].add(cat.split("=")[1])
      if not cat_ids and not conditions:
          return {"default": DataCategory(set(imap.keys()), {})}
      if cat_ids and not conditions:
          for sid, row in imap.items():
              cat_name = "_".join([row[cid] for cid in cat_ids])
              if cat_name not in table:
                  table[cat_name] = DataCategory(set(), {})
              table[cat_name].sids.add(sid)
          return table
      cond_ids = set()
      for k in conditions:
          try:
              cond_ids.add(header.index(k))
          except ValueError:
              continue
      idx_to_test = set(cat_ids).union(cond_ids)
      for sid, row in imap.items():
          if all([row[header.index(c)] in conditions[c] for c in conditions]):
              key = "_".join([row[idx] for idx in idx_to_test])
              try:
                  assert key in table.keys()
              except AssertionError:
                  table[key] = DataCategory(set(), {})
              table[key].sids.add(sid)
      try:
          assert len(table) > 0
      except AssertionError:
          return {"default": DataCategory(set(imap.keys()), {})}
      else:
          return table