nodes: 0, module; 1, function_definition; 2, function_name:_findRedundantProteins; 3, parameters; 4, block; 5, identifier:protToPeps; 6, identifier:pepToProts; 7, default_parameter; 8, expression_statement; 9, if_statement; 10, expression_statement; 11, expression_statement; 12, expression_statement; 13, expression_statement; 14, comment:#TODO: quick and dirty solution; 15, comment:#NOTE: add a test for merged proteins; 16, expression_statement; 17, for_statement; 18, expression_statement; 19, for_statement; 20, expression_statement; 21, expression_statement; 22, for_statement; 23, return_statement; 24, identifier:proteins; 25, None; 26, comment:"""Returns a set of proteins with redundant peptide evidence.
  
      After removing the redundant proteins from the "protToPeps" and "pepToProts"
      mapping, all remaining proteins have at least one unique peptide. The
      remaining proteins are a "minimal" set of proteins that are able to explain
      all peptides. However, this is not guaranteed to be the optimal solution
      with the least number of proteins. In addition it is possible that multiple
      solutions with the same number of "minimal" proteins exist.
  
      Procedure for finding the redundant proteins:
      1.  Generate a list of proteins that do not contain any unique peptides, a
          unique peptide has exactly one protein entry in "pepToProts".
      2.  Proteins are first sorted in ascending order of the number of peptides.
          Proteins with an equal number of peptides are sorted in descending order
              of their sorted peptide frequencies (= proteins per peptide).
          If two proteins are still equal, they are sorted alpha numerical in
          descending order according to their protein names. For example in the
          case of a tie between proteins "A" and "B", protein "B" would be
          removed.
      3.  Parse this list of sorted non unique proteins;
          If all its peptides have a frequency value of greater 1;
          mark the protein as redundant; remove its peptides from the peptide
          frequency count, continue with the next entry.
      4.  Return the set of proteins marked as redundant.
  
      :param pepToProts: dict, for each peptide (=key) contains a set of parent
          proteins (=value). For Example {peptide: {protein, ...}, ...}
      :param protToPeps: dict, for each protein (=key) contains a set of
          associated peptides (=value). For Example {protein: {peptide, ...}, ...}
      :param proteins: iterable, proteins that are tested for being redundant. If
          None all proteins in "protToPeps" are parsed.
      :returns: a set of redundant proteins, i.e. proteins that are not necessary
          to explain all peptides
      """; 27, comparison_operator:proteins is None; 28, block; 29, assignment; 30, assignment; 31, assignment; 32, assignment; 33, assignment; 34, identifier:protein; 35, identifier:proteins; 36, block; 37, assignment; 38, identifier:protein; 39, call; 40, block; 41, assignment; 42, assignment; 43, identifier:protein; 44, identifier:sortedProteins; 45, block; 46, identifier:redundantProteins; 47, identifier:proteins; 48, None; 49, expression_statement; 50, identifier:pepFrequency; 51, call; 52, identifier:protPepCounts; 53, call; 54, identifier:getCount; 55, call; 56, identifier:getProt; 57, call; 58, identifier:proteinTuples; 59, call; 60, if_statement; 61, identifier:sort; 62, call; 63, identifier:sorted; 64, argument_list; 65, if_statement; 66, expression_statement; 67, if_statement; 68, identifier:sortedProteins; 69, call; 70, identifier:redundantProteins; 71, call; 72, for_statement; 73, assignment; 74, identifier:_getValueCounts; 75, argument_list; 76, identifier:_getValueCounts; 77, argument_list; 78, attribute; 79, argument_list; 80, attribute; 81, argument_list; 82, identifier:list; 83, argument_list; 84, call; 85, block; 86, else_clause; 87, identifier:list; 88, argument_list; 89, identifier:proteinTuples; 90, keyword_argument; 91, comparison_operator:len(protein) == 1; 92, block; 93, assignment; 94, comparison_operator:min(protPepFreq) > 1; 95, block; 96, identifier:map; 97, argument_list; 98, identifier:set; 99, argument_list; 100, identifier:pep; 101, subscript; 102, block; 103, else_clause; 104, identifier:proteins; 105, call; 106, identifier:pepToProts; 107, identifier:protToPeps; 108, identifier:operator; 109, identifier:itemgetter; 110, integer:1; 111, identifier:operator; 112, identifier:itemgetter; 113, integer:0; 114, identifier:isinstance; 115, argument_list; 116, expression_statement; 117, block; 118, identifier:reverse; 119, True; 120, call; 121, integer:1; 122, expression_statement; 123, identifier:protPepFreq; 124, list_comprehension; 125, call; 126, integer:1; 127, expression_statement; 128, expression_statement; 129, identifier:getProt; 130, call; 131, identifier:protToPeps; 132, identifier:protein; 133, if_statement; 134, block; 135, identifier:viewkeys; 136, argument_list; 137, identifier:protein; 138, identifier:tuple; 139, call; 140, expression_statement; 141, identifier:len; 142, argument_list; 143, assignment; 144, subscript; 145, for_in_clause; 146, identifier:min; 147, argument_list; 148, assignment; 149, call; 150, identifier:sorted; 151, argument_list; 152, comparison_operator:pepFrequency[pep] <= 1; 153, block; 154, expression_statement; 155, expression_statement; 156, expression_statement; 157, identifier:protToPeps; 158, attribute; 159, argument_list; 160, call; 161, identifier:protein; 162, identifier:protein; 163, subscript; 164, identifier:pepFrequency; 165, identifier:pep; 166, identifier:pep; 167, subscript; 168, identifier:protPepFreq; 169, identifier:sortValue; 170, tuple; 171, attribute; 172, argument_list; 173, identifier:sort; 174, keyword_argument; 175, keyword_argument; 176, subscript; 177, integer:1; 178, break_statement; 179, assignment; 180, call; 181, call; 182, identifier:proteinTuples; 183, identifier:append; 184, identifier:protein; 185, attribute; 186, argument_list; 187, identifier:protein; 188, integer:0; 189, identifier:protToPeps; 190, identifier:protein; 191, binary_operator:len(protPepFreq)*-1; 192, call; 193, identifier:sort; 194, identifier:append; 195, tuple; 196, identifier:key; 197, identifier:getCount; 198, identifier:reverse; 199, True; 200, identifier:pepFrequency; 201, identifier:pep; 202, identifier:protPepFrequency; 203, call; 204, attribute; 205, argument_list; 206, attribute; 207, argument_list; 208, identifier:proteinTuples; 209, identifier:append; 210, call; 211, call; 212, unary_operator; 213, identifier:sorted; 214, argument_list; 215, identifier:protein; 216, identifier:sortValue; 217, identifier:Counter; 218, argument_list; 219, identifier:pepFrequency; 220, identifier:subtract; 221, identifier:protPepFrequency; 222, identifier:redundantProteins; 223, identifier:add; 224, identifier:protein; 225, identifier:tuple; 226, argument_list; 227, identifier:len; 228, argument_list; 229, integer:1; 230, identifier:protPepFreq; 231, keyword_argument; 232, subscript; 233, list; 234, identifier:protPepFreq; 235, identifier:reverse; 236, True; 237, identifier:protToPeps; 238, identifier:protein; 239, identifier:protein
code: def _findRedundantProteins(protToPeps, pepToProts, proteins=None):
      """Returns a set of proteins with redundant peptide evidence.
  
      After removing the redundant proteins from the "protToPeps" and "pepToProts"
      mapping, all remaining proteins have at least one unique peptide. The
      remaining proteins are a "minimal" set of proteins that are able to explain
      all peptides. However, this is not guaranteed to be the optimal solution
      with the least number of proteins. In addition it is possible that multiple
      solutions with the same number of "minimal" proteins exist.
  
      Procedure for finding the redundant proteins:
      1.  Generate a list of proteins that do not contain any unique peptides, a
          unique peptide has exactly one protein entry in "pepToProts".
      2.  Proteins are first sorted in ascending order of the number of peptides.
          Proteins with an equal number of peptides are sorted in descending order
              of their sorted peptide frequencies (= proteins per peptide).
          If two proteins are still equal, they are sorted alpha numerical in
          descending order according to their protein names. For example in the
          case of a tie between proteins "A" and "B", protein "B" would be
          removed.
      3.  Parse this list of sorted non unique proteins;
          If all its peptides have a frequency value of greater 1;
          mark the protein as redundant; remove its peptides from the peptide
          frequency count, continue with the next entry.
      4.  Return the set of proteins marked as redundant.
  
      :param pepToProts: dict, for each peptide (=key) contains a set of parent
          proteins (=value). For Example {peptide: {protein, ...}, ...}
      :param protToPeps: dict, for each protein (=key) contains a set of
          associated peptides (=value). For Example {protein: {peptide, ...}, ...}
      :param proteins: iterable, proteins that are tested for being redundant. If
          None all proteins in "protToPeps" are parsed.
      :returns: a set of redundant proteins, i.e. proteins that are not necessary
          to explain all peptides
      """
      if proteins is None:
          proteins = viewkeys(protToPeps)
  
      pepFrequency = _getValueCounts(pepToProts)
      protPepCounts = _getValueCounts(protToPeps)
  
      getCount = operator.itemgetter(1)
      getProt = operator.itemgetter(0)
  
      #TODO: quick and dirty solution
      #NOTE: add a test for merged proteins
      proteinTuples = list()
      for protein in proteins:
          if isinstance(protein, tuple):
              proteinTuples.append(protein)
          else:
              proteinTuples.append(tuple([protein]))
  
      sort = list()
      for protein in sorted(proteinTuples, reverse=True):
          if len(protein) == 1:
              protein = protein[0]
  
          protPepFreq = [pepFrequency[pep] for pep in protToPeps[protein]]
          if min(protPepFreq) > 1:
              sortValue = (len(protPepFreq)*-1, sorted(protPepFreq, reverse=True))
              sort.append((protein, sortValue))
      sortedProteins = map(getProt, sorted(sort, key=getCount, reverse=True))
  
      redundantProteins = set()
      for protein in sortedProteins:
          for pep in protToPeps[protein]:
              if pepFrequency[pep] <= 1:
                  break
          else:
              protPepFrequency = Counter(protToPeps[protein])
              pepFrequency.subtract(protPepFrequency)
              redundantProteins.add(protein)
      return redundantProteins