nodes: 0, module; 1, function_definition; 2, function_name:gather_categories; 3, parameters; 4, block; 5, identifier:imap; 6, identifier:header; 7, default_parameter; 8, expression_statement; 9, comment:# If no categories provided, return all SampleIDs; 10, if_statement; 11, expression_statement; 12, expression_statement; 13, expression_statement; 14, for_statement; 15, comment:# If invalid categories or conditions identified, return all SampleIDs; 16, if_statement; 17, comment:#If only category column given, return column-wise SampleIDs; 18, if_statement; 19, comment:# Collect all condition names; 20, expression_statement; 21, for_statement; 22, expression_statement; 23, comment:# If column name and condition given, return overlapping SampleIDs of column and; 24, comment:# condition combinations; 25, for_statement; 26, try_statement; 27, identifier:categories; 28, None; 29, comment:"""
      Find the user specified categories in the map and create a dictionary to contain the
      relevant data for each type within the categories. Multiple categories will have their
      types combined such that each possible combination will have its own entry in the
      dictionary.
  
      :type imap: dict
      :param imap: The input mapping file data keyed by SampleID
      :type header: list
      :param header: The header line from the input mapping file. This will be searched for
                     the user-specified categories
      :type categories: list
      :param categories: The list of user-specified category column name from mapping file
      :rtype: dict
      :return: A sorted dictionary keyed on the combinations of all the types found within
               the user-specified categories. Each entry will contain an empty DataCategory
               namedtuple. If no categories are specified, a single entry with the key
               'default' will be returned
      """; 30, comparison_operator:categories is None; 31, block; 32, assignment; 33, assignment; 34, assignment; 35, pattern_list; 36, call; 37, block; 38, boolean_operator; 39, block; 40, boolean_operator; 41, block; 42, assignment; 43, identifier:k; 44, identifier:conditions; 45, block; 46, assignment; 47, pattern_list; 48, call; 49, block; 50, block; 51, except_clause; 52, else_clause; 53, identifier:categories; 54, None; 55, return_statement; 56, identifier:cat_ids; 57, list_comprehension; 58, identifier:table; 59, call; 60, identifier:conditions; 61, call; 62, identifier:i; 63, identifier:cat; 64, identifier:enumerate; 65, argument_list; 66, if_statement; 67, not_operator; 68, not_operator; 69, return_statement; 70, identifier:cat_ids; 71, not_operator; 72, for_statement; 73, return_statement; 74, identifier:cond_ids; 75, call; 76, try_statement; 77, identifier:idx_to_test; 78, call; 79, identifier:sid; 80, identifier:row; 81, attribute; 82, argument_list; 83, if_statement; 84, assert_statement; 85, identifier:AssertionError; 86, block; 87, block; 88, dictionary; 89, call; 90, for_in_clause; 91, if_clause; 92, identifier:OrderedDict; 93, argument_list; 94, identifier:defaultdict; 95, argument_list; 96, identifier:categories; 97, boolean_operator; 98, block; 99, identifier:cat_ids; 100, identifier:conditions; 101, dictionary; 102, identifier:conditions; 103, pattern_list; 104, call; 105, block; 106, identifier:table; 107, identifier:set; 108, argument_list; 109, block; 110, except_clause; 111, attribute; 112, argument_list; 113, identifier:imap; 114, identifier:items; 115, call; 116, block; 117, comparison_operator:len(table) > 0; 118, return_statement; 119, return_statement; 120, pair; 121, attribute; 122, argument_list; 123, identifier:cat; 124, identifier:categories; 125, boolean_operator; 126, identifier:set; 127, comparison_operator:"=" in cat; 128, comparison_operator:cat.split("=")[0] in header; 129, expression_statement; 130, expression_statement; 131, pair; 132, identifier:sid; 133, identifier:row; 134, attribute; 135, argument_list; 136, expression_statement; 137, if_statement; 138, expression_statement; 139, expression_statement; 140, identifier:ValueError; 141, block; 142, call; 143, identifier:union; 144, identifier:cond_ids; 145, identifier:all; 146, argument_list; 147, expression_statement; 148, try_statement; 149, expression_statement; 150, call; 151, integer:0; 152, dictionary; 153, identifier:table; 154, string:"default"; 155, call; 156, identifier:header; 157, identifier:index; 158, identifier:cat; 159, comparison_operator:cat in header; 160, comparison_operator:"=" not in cat; 161, string:"="; 162, identifier:cat; 163, subscript; 164, identifier:header; 165, assignment; 166, call; 167, string:"default"; 168, call; 169, identifier:imap; 170, identifier:items; 171, assignment; 172, comparison_operator:cat_name not in table; 173, block; 174, call; 175, call; 176, continue_statement; 177, identifier:set; 178, argument_list; 179, list_comprehension; 180, assignment; 181, block; 182, except_clause; 183, call; 184, identifier:len; 185, argument_list; 186, pair; 187, identifier:DataCategory; 188, argument_list; 189, identifier:cat; 190, identifier:header; 191, string:"="; 192, identifier:cat; 193, call; 194, integer:0; 195, identifier:cat_name; 196, subscript; 197, attribute; 198, argument_list; 199, identifier:DataCategory; 200, argument_list; 201, identifier:cat_name; 202, call; 203, identifier:cat_name; 204, identifier:table; 205, expression_statement; 206, attribute; 207, argument_list; 208, attribute; 209, argument_list; 210, identifier:cat_ids; 211, comparison_operator:row[header.index(c)] in conditions[c]; 212, for_in_clause; 213, identifier:key; 214, call; 215, assert_statement; 216, identifier:AssertionError; 217, block; 218, attribute; 219, argument_list; 220, identifier:table; 221, string:"default"; 222, call; 223, call; 224, dictionary; 225, attribute; 226, argument_list; 227, identifier:header; 228, call; 229, subscript; 230, identifier:add; 231, subscript; 232, call; 233, dictionary; 234, attribute; 235, argument_list; 236, assignment; 237, attribute; 238, identifier:add; 239, identifier:sid; 240, identifier:cond_ids; 241, identifier:add; 242, call; 243, subscript; 244, subscript; 245, identifier:c; 246, identifier:conditions; 247, attribute; 248, argument_list; 249, comparison_operator:key in table.keys(); 250, expression_statement; 251, attribute; 252, identifier:add; 253, identifier:sid; 254, identifier:DataCategory; 255, argument_list; 256, identifier:set; 257, argument_list; 258, identifier:cat; 259, identifier:split; 260, string:"="; 261, attribute; 262, argument_list; 263, identifier:conditions; 264, identifier:cat_name; 265, call; 266, integer:1; 267, identifier:set; 268, argument_list; 269, string:"_"; 270, identifier:join; 271, list_comprehension; 272, subscript; 273, call; 274, subscript; 275, identifier:sids; 276, attribute; 277, argument_list; 278, identifier:row; 279, call; 280, identifier:conditions; 281, identifier:c; 282, string:"_"; 283, identifier:join; 284, list_comprehension; 285, identifier:key; 286, call; 287, assignment; 288, subscript; 289, identifier:sids; 290, call; 291, dictionary; 292, call; 293, identifier:header; 294, identifier:index; 295, subscript; 296, attribute; 297, argument_list; 298, call; 299, subscript; 300, for_in_clause; 301, identifier:table; 302, identifier:cat_name; 303, identifier:DataCategory; 304, argument_list; 305, identifier:table; 306, identifier:cat_name; 307, identifier:header; 308, identifier:index; 309, identifier:k; 310, attribute; 311, argument_list; 312, subscript; 313, for_in_clause; 314, attribute; 315, argument_list; 316, subscript; 317, call; 318, identifier:table; 319, identifier:key; 320, identifier:set; 321, argument_list; 322, attribute; 323, argument_list; 324, call; 325, integer:0; 326, identifier:cat; 327, identifier:split; 328, string:"="; 329, attribute; 330, argument_list; 331, identifier:row; 332, identifier:cid; 333, identifier:cid; 334, identifier:cat_ids; 335, call; 336, dictionary; 337, identifier:header; 338, identifier:index; 339, identifier:c; 340, identifier:row; 341, identifier:idx; 342, identifier:idx; 343, identifier:idx_to_test; 344, identifier:table; 345, identifier:keys; 346, identifier:table; 347, identifier:key; 348, identifier:DataCategory; 349, argument_list; 350, call; 351, identifier:imap; 352, identifier:keys; 353, attribute; 354, argument_list; 355, identifier:imap; 356, identifier:keys; 357, identifier:set; 358, argument_list; 359, call; 360, dictionary; 361, attribute; 362, argument_list; 363, identifier:cat; 364, identifier:split; 365, string:"="; 366, identifier:set; 367, argument_list; 368, identifier:imap; 369, identifier:keys
code: def gather_categories(imap, header, categories=None):
      """
      Find the user specified categories in the map and create a dictionary to contain the
      relevant data for each type within the categories. Multiple categories will have their
      types combined such that each possible combination will have its own entry in the
      dictionary.
  
      :type imap: dict
      :param imap: The input mapping file data keyed by SampleID
      :type header: list
      :param header: The header line from the input mapping file. This will be searched for
                     the user-specified categories
      :type categories: list
      :param categories: The list of user-specified category column name from mapping file
      :rtype: dict
      :return: A sorted dictionary keyed on the combinations of all the types found within
               the user-specified categories. Each entry will contain an empty DataCategory
               namedtuple. If no categories are specified, a single entry with the key
               'default' will be returned
      """
      # If no categories provided, return all SampleIDs
      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 invalid categories or conditions identified, return all SampleIDs
      if not cat_ids and not conditions:
          return {"default": DataCategory(set(imap.keys()), {})}
  
      #If only category column given, return column-wise SampleIDs
      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
  
      # Collect all condition names
      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)
  
      # If column name and condition given, return overlapping SampleIDs of column and
      # condition combinations
      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