nodes: 0, module; 1, function_definition; 2, function_name:subtract_ranges; 3, parameters; 4, block; 5, identifier:r1s; 6, identifier:r2s; 7, default_parameter; 8, expression_statement; 9, import_from_statement; 10, if_statement; 11, expression_statement; 12, expression_statement; 13, expression_statement; 14, expression_statement; 15, for_statement; 16, comment:#outputs = merge_ranges(outputs); 17, comment:#print [x.get_range_string() for x in outputs]; 18, return_statement; 19, identifier:already_sorted; 20, False; 21, comment:"""Subtract multiple ranges from a list of ranges
  
    :param r1s: range list 1
    :param r2s: range list 2
    :param already_sorted: default (False)
    :type r1s: GenomicRange[]
    :type r2s: GenomicRange[]
  
    :return: new range r1s minus r2s
    :rtype: GenomicRange[]
    """; 22, dotted_name; 23, dotted_name; 24, not_operator; 25, block; 26, assignment; 27, assignment; 28, assignment; 29, assignment; 30, identifier:loc; 31, identifier:mls; 32, comment:#[beds1,beds2] = loc.get_payload(); 33, block; 34, call; 35, identifier:seqtools; 36, identifier:stream; 37, identifier:MultiLocusStream; 38, identifier:already_sorted; 39, expression_statement; 40, expression_statement; 41, identifier:outputs; 42, list; 43, identifier:mls; 44, call; 45, identifier:tot1; 46, integer:0; 47, identifier:tot2; 48, integer:0; 49, expression_statement; 50, comment:#print v; 51, expression_statement; 52, expression_statement; 53, expression_statement; 54, if_statement; 55, if_statement; 56, comment:#this loop could be made much more efficient; 57, expression_statement; 58, comment:#keyed by beds1 index stores list of overlaping beds2 indecies; 59, for_statement; 60, expression_statement; 61, expression_statement; 62, for_statement; 63, for_statement; 64, comment:#while len(beds2) > 0:; 65, comment:#  b2 = beds2.pop(0); 66, comment:#  vs = [x.subtract(b2) for x in beds1]; 67, comment:#  tot = []; 68, comment:#  for res in vs:; 69, comment:#    tot = tot + res; 70, comment:#  beds1 = tot; 71, comment:#print "subtract "+str(len(beds1))+"\t"+str(len(beds2)); 72, comment:#print beds1[0].get_range_string(); 73, identifier:merge_ranges; 74, argument_list; 75, assignment; 76, assignment; 77, identifier:MultiLocusStream; 78, argument_list; 79, assignment; 80, assignment; 81, assignment; 82, assignment; 83, comparison_operator:len(beds1)==0; 84, block; 85, comparison_operator:len(beds2)==0; 86, block; 87, assignment; 88, identifier:i; 89, call; 90, block; 91, assignment; 92, assignment; 93, identifier:i; 94, call; 95, block; 96, identifier:i; 97, call; 98, block; 99, identifier:outputs; 100, identifier:r1s; 101, call; 102, identifier:r2s; 103, call; 104, list; 105, identifier:v; 106, attribute; 107, list_pattern; 108, identifier:v; 109, identifier:beds1; 110, subscript; 111, identifier:beds2; 112, subscript; 113, call; 114, integer:0; 115, continue_statement; 116, call; 117, integer:0; 118, expression_statement; 119, continue_statement; 120, identifier:mapping; 121, dictionary; 122, identifier:range; 123, argument_list; 124, expression_statement; 125, identifier:beds2min; 126, integer:0; 127, identifier:beds2max; 128, call; 129, identifier:range; 130, argument_list; 131, for_statement; 132, identifier:range; 133, argument_list; 134, if_statement; 135, identifier:merge_ranges; 136, argument_list; 137, identifier:merge_ranges; 138, argument_list; 139, call; 140, call; 141, identifier:loc; 142, identifier:payload; 143, identifier:beds1; 144, identifier:beds2; 145, identifier:beds1; 146, slice; 147, identifier:beds2; 148, slice; 149, identifier:len; 150, argument_list; 151, identifier:len; 152, argument_list; 153, augmented_assignment; 154, integer:0; 155, call; 156, assignment; 157, identifier:len; 158, argument_list; 159, integer:0; 160, call; 161, identifier:j; 162, call; 163, block; 164, integer:0; 165, call; 166, comparison_operator:len(mapping[i])==0; 167, block; 168, else_clause; 169, identifier:r1s; 170, identifier:r2s; 171, identifier:BedArrayStream; 172, argument_list; 173, identifier:BedArrayStream; 174, argument_list; 175, identifier:beds1; 176, identifier:beds2; 177, identifier:outputs; 178, identifier:beds1; 179, identifier:len; 180, argument_list; 181, subscript; 182, list; 183, identifier:beds2; 184, identifier:len; 185, argument_list; 186, identifier:range; 187, argument_list; 188, expression_statement; 189, if_statement; 190, identifier:len; 191, argument_list; 192, call; 193, integer:0; 194, expression_statement; 195, block; 196, identifier:r1s; 197, identifier:r2s; 198, identifier:beds1; 199, identifier:mapping; 200, identifier:i; 201, identifier:beds1; 202, identifier:beds2min; 203, identifier:beds2max; 204, assignment; 205, comparison_operator:cmpval == -1; 206, block; 207, elif_clause; 208, else_clause; 209, identifier:beds1; 210, identifier:len; 211, argument_list; 212, augmented_assignment; 213, expression_statement; 214, identifier:cmpval; 215, call; 216, identifier:cmpval; 217, unary_operator; 218, expression_statement; 219, comparison_operator:cmpval == 0; 220, block; 221, block; 222, subscript; 223, identifier:outputs; 224, identifier:beds1; 225, augmented_assignment; 226, attribute; 227, argument_list; 228, integer:1; 229, assignment; 230, identifier:cmpval; 231, integer:0; 232, expression_statement; 233, break_statement; 234, identifier:mapping; 235, identifier:i; 236, identifier:outputs; 237, call; 238, subscript; 239, identifier:cmp; 240, subscript; 241, identifier:beds2min; 242, binary_operator:j+1; 243, call; 244, identifier:subtract_range_array; 245, argument_list; 246, identifier:beds1; 247, identifier:i; 248, identifier:beds2; 249, identifier:j; 250, identifier:j; 251, integer:1; 252, attribute; 253, argument_list; 254, subscript; 255, list_comprehension; 256, keyword_argument; 257, subscript; 258, identifier:append; 259, identifier:j; 260, identifier:beds1; 261, identifier:i; 262, subscript; 263, for_in_clause; 264, identifier:is_sorted; 265, True; 266, identifier:mapping; 267, identifier:i; 268, identifier:beds2; 269, identifier:j; 270, identifier:j; 271, subscript; 272, identifier:mapping; 273, identifier:i
code: def subtract_ranges(r1s,r2s,already_sorted=False):
    """Subtract multiple ranges from a list of ranges
  
    :param r1s: range list 1
    :param r2s: range list 2
    :param already_sorted: default (False)
    :type r1s: GenomicRange[]
    :type r2s: GenomicRange[]
  
    :return: new range r1s minus r2s
    :rtype: GenomicRange[]
    """
    from seqtools.stream import MultiLocusStream
    if not already_sorted:
      r1s = merge_ranges(r1s)
      r2s = merge_ranges(r2s)
    outputs = []
    mls = MultiLocusStream([BedArrayStream(r1s),BedArrayStream(r2s)])
    tot1 = 0
    tot2 = 0
    for loc in mls:
      #[beds1,beds2] = loc.get_payload()
      v = loc.payload
      #print v
      [beds1,beds2] =v
      beds1 = beds1[:]
      beds2 = beds2[:]
      if len(beds1)==0:
        continue
      if len(beds2)==0:
        outputs += beds1
        continue
      #this loop could be made much more efficient
      mapping = {} #keyed by beds1 index stores list of overlaping beds2 indecies
      for i in range(0,len(beds1)):
        mapping[i] = []
      beds2min = 0
      beds2max = len(beds2)
      for i in range(0,len(beds1)):
        for j in range(beds2min,beds2max):
          cmpval = beds1[i].cmp(beds2[j])
          if cmpval == -1:
            beds2min = j+1
          elif cmpval == 0:
            mapping[i].append(j)
          else:
            break
      for i in range(0,len(beds1)):
        if len(mapping[i])==0: outputs += beds1
        else:
          outputs += subtract_range_array(beds1[i],[beds2[j] for j in mapping[i]],is_sorted=True)
      #while len(beds2) > 0:
      #  b2 = beds2.pop(0)
      #  vs = [x.subtract(b2) for x in beds1]
      #  tot = []
      #  for res in vs:
      #    tot = tot + res
      #  beds1 = tot
      #print "subtract "+str(len(beds1))+"\t"+str(len(beds2))
      #print beds1[0].get_range_string()
    #outputs = merge_ranges(outputs)
    #print [x.get_range_string() for x in outputs]
  
    return merge_ranges(outputs)