nodes: 0, module; 1, function_definition; 2, function_name:select_segment; 3, parameters; 4, type; 5, block; 6, identifier:self; 7, identifier:segs; 8, identifier:segs_tips; 9, identifier:segs_undecided; 10, generic_type; 11, expression_statement; 12, expression_statement; 13, expression_statement; 14, for_statement; 15, expression_statement; 16, if_statement; 17, expression_statement; 18, return_statement; 19, identifier:Tuple; 20, type_parameter; 21, comment:"""Out of a list of line segments, choose segment that has the most
          distant second data point.
  
          Assume the distance matrix Ddiff is sorted according to seg_idcs.
          Compute all the distances.
  
          Returns
          -------
          iseg : int
              Index identifying the position within the list of line segments.
          tips3 : int
              Positions of tips within chosen segment.
          """; 22, assignment; 23, assignment; 24, pattern_list; 25, call; 26, comment:# do not consider too small segments; 27, block; 28, assignment; 29, comparison_operator:scores_tips[iseg, 0] == 0; 30, block; 31, assignment; 32, expression_list; 33, type; 34, type; 35, identifier:scores_tips; 36, call; 37, identifier:allindices; 38, call; 39, identifier:iseg; 40, identifier:seg; 41, identifier:enumerate; 42, argument_list; 43, if_statement; 44, comment:# restrict distance matrix to points in segment; 45, if_statement; 46, expression_statement; 47, if_statement; 48, comment:# map the global position to the position within the segment; 49, expression_statement; 50, comment:# find the third point on the segment that has maximal; 51, comment:# added distance from the two tip points; 52, expression_statement; 53, if_statement; 54, comment:# add this point to tips, it's a third tip, we store it at the first; 55, comment:# position in an array called tips3; 56, expression_statement; 57, if_statement; 58, expression_statement; 59, comment:# compute the score as ratio of the added distance to the third tip,; 60, comment:# to what it would be if it were on the straight line between the; 61, comment:# two first tips, given by Dseg[tips[:2]]; 62, comment:# if we did not normalize, there would be a danger of simply; 63, comment:# assigning the highest score to the longest segment; 64, expression_statement; 65, expression_statement; 66, comment:# simply the number of points; 67, expression_statement; 68, if_statement; 69, comment:# write result; 70, expression_statement; 71, expression_statement; 72, identifier:iseg; 73, call; 74, subscript; 75, integer:0; 76, return_statement; 77, identifier:tips3; 78, call; 79, identifier:iseg; 80, identifier:tips3; 81, identifier:int; 82, identifier:int; 83, attribute; 84, argument_list; 85, attribute; 86, argument_list; 87, identifier:segs; 88, comparison_operator:segs_tips[iseg][0] == -1; 89, block; 90, not_operator; 91, block; 92, else_clause; 93, assignment; 94, subscript; 95, comment:# check that none of our tips "connects" with a tip of the; 96, comment:# other segments; 97, block; 98, assignment; 99, assignment; 100, not_operator; 101, block; 102, assignment; 103, comparison_operator:third_maximizer is not None; 104, comment:# find a fourth point that has maximal distance to all three; 105, block; 106, assignment; 107, assignment; 108, assignment; 109, call; 110, comparison_operator:len(seg) <= self.min_group_size; 111, block; 112, assignment; 113, assignment; 114, attribute; 115, argument_list; 116, identifier:scores_tips; 117, identifier:iseg; 118, integer:0; 119, expression_list; 120, attribute; 121, argument_list; 122, identifier:np; 123, identifier:zeros; 124, tuple; 125, identifier:np; 126, identifier:arange; 127, subscript; 128, keyword_argument; 129, subscript; 130, unary_operator; 131, continue_statement; 132, call; 133, expression_statement; 134, block; 135, identifier:third_maximizer; 136, None; 137, identifier:segs_undecided; 138, identifier:iseg; 139, for_statement; 140, identifier:tips; 141, list_comprehension; 142, identifier:dseg; 143, binary_operator:Dseg[tips[0]] + Dseg[tips[1]]; 144, call; 145, continue_statement; 146, identifier:third_tip; 147, call; 148, identifier:third_maximizer; 149, None; 150, expression_statement; 151, expression_statement; 152, if_statement; 153, identifier:tips3; 154, call; 155, identifier:score; 156, binary_operator:dseg[tips3[2]] / Dseg[tips3[0], tips3[1]]; 157, identifier:score; 158, conditional_expression:len(seg) if self.choose_largest_segment else score; 159, attribute; 160, argument_list; 161, call; 162, attribute; 163, expression_statement; 164, subscript; 165, identifier:score; 166, subscript; 167, identifier:tips3; 168, identifier:np; 169, identifier:argmax; 170, subscript; 171, unary_operator; 172, None; 173, subscript; 174, identifier:astype; 175, identifier:int; 176, call; 177, integer:4; 178, attribute; 179, integer:0; 180, identifier:dtype; 181, identifier:int; 182, subscript; 183, integer:0; 184, integer:1; 185, identifier:isinstance; 186, argument_list; 187, assignment; 188, expression_statement; 189, identifier:jseg; 190, call; 191, block; 192, subscript; 193, for_in_clause; 194, subscript; 195, subscript; 196, attribute; 197, argument_list; 198, attribute; 199, argument_list; 200, augmented_assignment; 201, assignment; 202, boolean_operator; 203, block; 204, else_clause; 205, attribute; 206, argument_list; 207, subscript; 208, subscript; 209, call; 210, attribute; 211, identifier:score; 212, identifier:logg; 213, identifier:m; 214, string; 215, identifier:iseg; 216, string; 217, identifier:score; 218, string; 219, call; 220, conditional_expression:'(too small)' if len(seg) < self.min_group_size else ''; 221, keyword_argument; 222, identifier:len; 223, argument_list; 224, identifier:self; 225, identifier:min_group_size; 226, assignment; 227, identifier:scores_tips; 228, identifier:iseg; 229, integer:0; 230, identifier:scores_tips; 231, identifier:iseg; 232, slice; 233, identifier:scores_tips; 234, slice; 235, integer:0; 236, integer:1; 237, identifier:scores_tips; 238, identifier:iseg; 239, slice; 240, identifier:len; 241, argument_list; 242, attribute; 243, identifier:shape; 244, identifier:segs_tips; 245, identifier:iseg; 246, attribute; 247, identifier:OnFlySymMatrix; 248, identifier:Dseg; 249, subscript; 250, assignment; 251, identifier:range; 252, argument_list; 253, if_statement; 254, subscript; 255, integer:0; 256, identifier:tip; 257, subscript; 258, identifier:Dseg; 259, subscript; 260, identifier:Dseg; 261, subscript; 262, call; 263, identifier:any; 264, identifier:np; 265, identifier:argmax; 266, identifier:dseg; 267, identifier:dseg; 268, subscript; 269, identifier:fourth_tip; 270, call; 271, comparison_operator:fourth_tip != tips[0]; 272, comparison_operator:fourth_tip != third_tip; 273, expression_statement; 274, expression_statement; 275, block; 276, identifier:np; 277, identifier:append; 278, identifier:tips; 279, identifier:third_tip; 280, identifier:dseg; 281, subscript; 282, identifier:Dseg; 283, subscript; 284, subscript; 285, identifier:len; 286, argument_list; 287, identifier:self; 288, identifier:choose_largest_segment; 289, string_content:group; 290, string_content:score; 291, string_content:n_points; 292, identifier:len; 293, argument_list; 294, string; 295, comparison_operator:len(seg) < self.min_group_size; 296, string; 297, identifier:v; 298, integer:4; 299, identifier:seg; 300, identifier:score; 301, integer:0; 302, integer:1; 303, integer:1; 304, identifier:segs; 305, identifier:self; 306, identifier:_adata; 307, identifier:self; 308, identifier:distances_dpt; 309, attribute; 310, call; 311, identifier:Dseg; 312, call; 313, call; 314, comparison_operator:jseg != iseg; 315, comment:# take the inner tip, the "second tip" of the segment; 316, block; 317, call; 318, integer:0; 319, identifier:segs_tips; 320, identifier:iseg; 321, identifier:tips; 322, integer:0; 323, identifier:tips; 324, integer:1; 325, attribute; 326, argument_list; 327, identifier:Dseg; 328, identifier:third_tip; 329, attribute; 330, argument_list; 331, identifier:fourth_tip; 332, subscript; 333, identifier:fourth_tip; 334, identifier:third_tip; 335, assignment; 336, augmented_assignment; 337, expression_statement; 338, identifier:tips3; 339, integer:2; 340, identifier:tips3; 341, integer:0; 342, identifier:tips3; 343, integer:1; 344, identifier:seg; 345, identifier:seg; 346, string_content:(too small); 347, call; 348, attribute; 349, identifier:self; 350, identifier:distances_dpt; 351, attribute; 352, argument_list; 353, attribute; 354, argument_list; 355, identifier:len; 356, argument_list; 357, identifier:jseg; 358, identifier:iseg; 359, for_statement; 360, attribute; 361, argument_list; 362, identifier:np; 363, identifier:isfinite; 364, identifier:dseg; 365, identifier:np; 366, identifier:argmax; 367, identifier:dseg; 368, identifier:tips; 369, integer:0; 370, subscript; 371, identifier:fourth_tip; 372, identifier:dseg; 373, subscript; 374, augmented_assignment; 375, identifier:len; 376, argument_list; 377, identifier:self; 378, identifier:min_group_size; 379, identifier:np; 380, identifier:ix_; 381, identifier:seg; 382, identifier:seg; 383, attribute; 384, identifier:restrict; 385, identifier:seg; 386, identifier:segs; 387, identifier:itip; 388, call; 389, block; 390, identifier:np; 391, identifier:where; 392, comparison_operator:allindices[seg] == tip; 393, identifier:tips; 394, integer:1; 395, identifier:Dseg; 396, subscript; 397, identifier:dseg; 398, subscript; 399, identifier:seg; 400, identifier:self; 401, identifier:distances_dpt; 402, identifier:range; 403, argument_list; 404, if_statement; 405, subscript; 406, identifier:tip; 407, identifier:tips; 408, integer:1; 409, identifier:Dseg; 410, identifier:third_tip; 411, integer:2; 412, parenthesized_expression; 413, comment:# logg.m('    group', iseg, 'with tip', segs_tips[iseg][itip],; 414, comment:#        'connects with', jseg, 'with tip', segs_tips[jseg][1], v=4); 415, comment:# logg.m('    do not use the tip for "triangulation"', v=4); 416, block; 417, identifier:allindices; 418, identifier:seg; 419, comparison_operator:self.distances_dpt[segs_tips[jseg][1], segs_tips[iseg][itip]]
                                  < 0.5 * self.distances_dpt[segs_tips[iseg][~itip], segs_tips[iseg][itip]]; 420, expression_statement; 421, subscript; 422, binary_operator:0.5 * self.distances_dpt[segs_tips[iseg][~itip], segs_tips[iseg][itip]]; 423, assignment; 424, attribute; 425, subscript; 426, subscript; 427, float:0.5; 428, subscript; 429, identifier:third_maximizer; 430, identifier:itip; 431, identifier:self; 432, identifier:distances_dpt; 433, subscript; 434, integer:1; 435, subscript; 436, identifier:itip; 437, attribute; 438, subscript; 439, subscript; 440, identifier:segs_tips; 441, identifier:jseg; 442, identifier:segs_tips; 443, identifier:iseg; 444, identifier:self; 445, identifier:distances_dpt; 446, subscript; 447, unary_operator; 448, subscript; 449, identifier:itip; 450, identifier:segs_tips; 451, identifier:iseg; 452, identifier:itip; 453, identifier:segs_tips; 454, identifier:iseg
code: def select_segment(self, segs, segs_tips, segs_undecided) -> Tuple[int, int]:
          """Out of a list of line segments, choose segment that has the most
          distant second data point.
  
          Assume the distance matrix Ddiff is sorted according to seg_idcs.
          Compute all the distances.
  
          Returns
          -------
          iseg : int
              Index identifying the position within the list of line segments.
          tips3 : int
              Positions of tips within chosen segment.
          """
          scores_tips = np.zeros((len(segs), 4))
          allindices = np.arange(self._adata.shape[0], dtype=int)
          for iseg, seg in enumerate(segs):
              # do not consider too small segments
              if segs_tips[iseg][0] == -1: continue
              # restrict distance matrix to points in segment
              if not isinstance(self.distances_dpt, OnFlySymMatrix):
                  Dseg = self.distances_dpt[np.ix_(seg, seg)]
              else:
                  Dseg = self.distances_dpt.restrict(seg)
              third_maximizer = None
              if segs_undecided[iseg]:
                  # check that none of our tips "connects" with a tip of the
                  # other segments
                  for jseg in range(len(segs)):
                      if jseg != iseg:
                          # take the inner tip, the "second tip" of the segment
                          for itip in range(2):
                              if (self.distances_dpt[segs_tips[jseg][1], segs_tips[iseg][itip]]
                                  < 0.5 * self.distances_dpt[segs_tips[iseg][~itip], segs_tips[iseg][itip]]):
                                  # logg.m('    group', iseg, 'with tip', segs_tips[iseg][itip],
                                  #        'connects with', jseg, 'with tip', segs_tips[jseg][1], v=4)
                                  # logg.m('    do not use the tip for "triangulation"', v=4)
                                  third_maximizer = itip
              # map the global position to the position within the segment
              tips = [np.where(allindices[seg] == tip)[0][0]
                      for tip in segs_tips[iseg]]
              # find the third point on the segment that has maximal
              # added distance from the two tip points
              dseg = Dseg[tips[0]] + Dseg[tips[1]]
              if not np.isfinite(dseg).any():
                  continue
              # add this point to tips, it's a third tip, we store it at the first
              # position in an array called tips3
              third_tip = np.argmax(dseg)
              if third_maximizer is not None:
                  # find a fourth point that has maximal distance to all three
                  dseg += Dseg[third_tip]
                  fourth_tip = np.argmax(dseg)
                  if fourth_tip != tips[0] and fourth_tip != third_tip:
                      tips[1] = fourth_tip
                      dseg -= Dseg[tips[1]]
                  else:
                      dseg -= Dseg[third_tip]
              tips3 = np.append(tips, third_tip)
              # compute the score as ratio of the added distance to the third tip,
              # to what it would be if it were on the straight line between the
              # two first tips, given by Dseg[tips[:2]]
              # if we did not normalize, there would be a danger of simply
              # assigning the highest score to the longest segment
              score = dseg[tips3[2]] / Dseg[tips3[0], tips3[1]]
              score = len(seg) if self.choose_largest_segment else score  # simply the number of points
              logg.m('    group', iseg, 'score', score, 'n_points', len(seg),
                     '(too small)' if len(seg) < self.min_group_size else '', v=4)
              if len(seg) <= self.min_group_size: score = 0
              # write result
              scores_tips[iseg, 0] = score
              scores_tips[iseg, 1:] = tips3
          iseg = np.argmax(scores_tips[:, 0])
          if scores_tips[iseg, 0] == 0: return -1, None
          tips3 = scores_tips[iseg, 1:].astype(int)
          return iseg, tips3