nodes: 0, module; 1, function_definition; 2, function_name:image_position_stochastic; 3, parameters; 4, block; 5, identifier:self; 6, identifier:source_x; 7, identifier:source_y; 8, identifier:kwargs_lens; 9, default_parameter; 10, default_parameter; 11, default_parameter; 12, default_parameter; 13, default_parameter; 14, default_parameter; 15, default_parameter; 16, expression_statement; 17, expression_statement; 18, for_statement; 19, expression_statement; 20, if_statement; 21, return_statement; 22, identifier:search_window; 23, integer:10; 24, identifier:precision_limit; 25, binary_operator:10**(-10); 26, identifier:arrival_time_sort; 27, True; 28, identifier:x_center; 29, integer:0; 30, identifier:y_center; 31, integer:0; 32, identifier:num_random; 33, integer:1000; 34, identifier:verbose; 35, False; 36, comment:"""
          Solves the lens equation stochastically with the scipy minimization routine on the quadratic distance between
          the backwards ray-shooted proposed image position and the source position.
          Credits to Giulia Pagano
  
          :param source_x: source position
          :param source_y: source position
          :param kwargs_lens: lens model list of keyword arguments
          :param search_window: angular size of search window
          :param precision_limit: limit required on the precision in the source plane
          :param arrival_time_sort: bool, if True sorts according to arrival time
          :param x_center: center of search window
          :param y_center: center of search window
          :param num_random: number of random starting points of the non-linear solver in the search window
          :param verbose: bool, if True, prints performance information
          :return: x_image, y_image
          """; 37, assignment; 38, identifier:i; 39, call; 40, block; 41, assignment; 42, comparison_operator:arrival_time_sort is True; 43, block; 44, expression_list; 45, integer:10; 46, parenthesized_expression; 47, pattern_list; 48, expression_list; 49, identifier:range; 50, argument_list; 51, expression_statement; 52, expression_statement; 53, expression_statement; 54, expression_statement; 55, if_statement; 56, pattern_list; 57, call; 58, identifier:arrival_time_sort; 59, True; 60, expression_statement; 61, identifier:x_mins; 62, identifier:y_mins; 63, unary_operator; 64, identifier:x_solve; 65, identifier:y_solve; 66, list; 67, list; 68, identifier:num_random; 69, assignment; 70, assignment; 71, assignment; 72, assignment; 73, comparison_operator:self._root(result.x, kwargs_lens, source_x, source_y) < precision_limit**2; 74, block; 75, identifier:x_mins; 76, identifier:y_mins; 77, attribute; 78, argument_list; 79, assignment; 80, integer:10; 81, identifier:x_init; 82, binary_operator:np.random.uniform(-search_window / 2., search_window / 2) + x_center; 83, identifier:y_init; 84, binary_operator:np.random.uniform(-search_window / 2., search_window / 2) + y_center; 85, identifier:xinitial; 86, call; 87, identifier:result; 88, call; 89, call; 90, binary_operator:precision_limit**2; 91, expression_statement; 92, expression_statement; 93, identifier:image_util; 94, identifier:findOverlap; 95, identifier:x_solve; 96, identifier:y_solve; 97, identifier:precision_limit; 98, pattern_list; 99, call; 100, call; 101, identifier:x_center; 102, call; 103, identifier:y_center; 104, attribute; 105, argument_list; 106, identifier:minimize; 107, argument_list; 108, attribute; 109, argument_list; 110, identifier:precision_limit; 111, integer:2; 112, call; 113, call; 114, identifier:x_mins; 115, identifier:y_mins; 116, attribute; 117, argument_list; 118, attribute; 119, argument_list; 120, attribute; 121, argument_list; 122, identifier:np; 123, identifier:array; 124, list; 125, attribute; 126, identifier:xinitial; 127, keyword_argument; 128, keyword_argument; 129, keyword_argument; 130, identifier:self; 131, identifier:_root; 132, attribute; 133, identifier:kwargs_lens; 134, identifier:source_x; 135, identifier:source_y; 136, attribute; 137, argument_list; 138, attribute; 139, argument_list; 140, identifier:self; 141, identifier:sort_arrival_times; 142, identifier:x_mins; 143, identifier:y_mins; 144, identifier:kwargs_lens; 145, attribute; 146, identifier:uniform; 147, binary_operator:-search_window / 2.; 148, binary_operator:search_window / 2; 149, attribute; 150, identifier:uniform; 151, binary_operator:-search_window / 2.; 152, binary_operator:search_window / 2; 153, identifier:x_init; 154, identifier:y_init; 155, identifier:self; 156, identifier:_root; 157, identifier:args; 158, tuple; 159, identifier:tol; 160, binary_operator:precision_limit ** 2; 161, identifier:method; 162, string; 163, identifier:result; 164, identifier:x; 165, identifier:x_solve; 166, identifier:append; 167, subscript; 168, identifier:y_solve; 169, identifier:append; 170, subscript; 171, identifier:np; 172, identifier:random; 173, unary_operator; 174, float:2.; 175, identifier:search_window; 176, integer:2; 177, identifier:np; 178, identifier:random; 179, unary_operator; 180, float:2.; 181, identifier:search_window; 182, integer:2; 183, identifier:kwargs_lens; 184, identifier:source_x; 185, identifier:source_y; 186, identifier:precision_limit; 187, integer:2; 188, string_content:Nelder-Mead; 189, attribute; 190, integer:0; 191, attribute; 192, integer:1; 193, identifier:search_window; 194, identifier:search_window; 195, identifier:result; 196, identifier:x; 197, identifier:result; 198, identifier:x
code: def image_position_stochastic(self, source_x, source_y, kwargs_lens, search_window=10,
                                    precision_limit=10**(-10), arrival_time_sort=True, x_center=0,
                                    y_center=0, num_random=1000, verbose=False):
          """
          Solves the lens equation stochastically with the scipy minimization routine on the quadratic distance between
          the backwards ray-shooted proposed image position and the source position.
          Credits to Giulia Pagano
  
          :param source_x: source position
          :param source_y: source position
          :param kwargs_lens: lens model list of keyword arguments
          :param search_window: angular size of search window
          :param precision_limit: limit required on the precision in the source plane
          :param arrival_time_sort: bool, if True sorts according to arrival time
          :param x_center: center of search window
          :param y_center: center of search window
          :param num_random: number of random starting points of the non-linear solver in the search window
          :param verbose: bool, if True, prints performance information
          :return: x_image, y_image
          """
          x_solve, y_solve = [], []
          for i in range(num_random):
              x_init = np.random.uniform(-search_window / 2., search_window / 2) + x_center
              y_init = np.random.uniform(-search_window / 2., search_window / 2) + y_center
              xinitial = np.array([x_init, y_init])
              result = minimize(self._root, xinitial, args=(kwargs_lens, source_x, source_y), tol=precision_limit ** 2, method='Nelder-Mead')
              if self._root(result.x, kwargs_lens, source_x, source_y) < precision_limit**2:
                  x_solve.append(result.x[0])
                  y_solve.append(result.x[1])
  
          x_mins, y_mins = image_util.findOverlap(x_solve, y_solve, precision_limit)
          if arrival_time_sort is True:
              x_mins, y_mins = self.sort_arrival_times(x_mins, y_mins, kwargs_lens)
          return x_mins, y_mins