//  [python]
def fetch_data(self, view_camera):
        
        outputs = render(view_camera, self.engine, self.opt, self.bg_color)

        # --- RGB image --- #
        img = outputs["render"].permute(1, 2, 0)  #
        rgb_score = img.clone()
        depth_score = rgb_score.cpu().numpy().reshape(-1)

        # --- semantic image --- #
        sems = outputs["render_object"].permute(1, 2, 0)
        H, W, C = sems.shape
        sems /= (torch.norm(sems, dim=-1, keepdim=True) + 1e-6)
        sem_transed = sems @ self.proj_mat
        sem_transed_rgb = torch.clip(sem_transed*0.5+0.5, 0, 1)

        if self.clear_edit:
            self.new_click_xy = []
            self.clear_edit = False
            self.prompt_num = 0
        
        if self.reload_flag:
            self.reload_flag = False
            self.engine.load_ply(self.opt.ply_path)
            print("Reload original 3D Gaussians from: ", self.opt.ply_path)


        if len(self.new_click_xy) > 0:

            featmap = sems.reshape(H, W, -1)
            
            if self.new_click:
                xy = self.new_click_xy
                new_feat = featmap[int(xy[1])%H, int(xy[0])%W, :].reshape(featmap.shape[-1], -1)
                if (self.prompt_num == 0) or (self.clickmode_multi_button == False):
                    self.chosen_feature = new_feat
                else:
                    self.chosen_feature = torch.cat([self.chosen_feature, new_feat], dim=-1)    # extend to get more prompt features
                self.prompt_num += 1
                self.new_click = False
            
            score_map = featmap @ self.chosen_feature

            score_map = (score_map + 1.0) / 2
            score_binary = score_map > dpg.get_value('_ScoreThres')
            
            score_map[~score_binary] = 0.0
            score_map = torch.max(score_map, dim=-1).values
            score_norm = (score_map - dpg.get_value('_ScoreThres')) / (1 - dpg.get_value('_ScoreThres'))

            if self.binary_threshold_button:
                rgb_score = img * torch.max(score_binary, dim=-1, keepdim=True).values    # option: binary
            else:
                rgb_score = img * score_norm[:, :, None]
            depth_score = 1 - torch.clip(score_norm, 0, 1)
            depth_score = depth2img(depth_score.cpu().numpy()).astype(np.float32)/255.0

            if self.segment3d_flag:
                """ gaussian point cloud core params
                self.engine._xyz            # (N, 3)
                self.engine._features_dc    # (N, 1, 3)
                self.engine._features_rest  # (N, 15, 3)
                self.engine._opacity        # (N, 1)
                self.engine._scaling        # (N, 3)
                self.engine._rotation       # (N, 4)
                self.engine._objects_dc     # (N, 1, 16)
                """
                self.segment3d_flag = False
                feat_pts = self.engine._objects_dc.squeeze()
                feat_pts /= (torch.norm(feat_pts, dim=-1, keepdim=True) + 1e-6)
                score_pts = feat_pts @ self.chosen_feature
                score_pts = (score_pts + 1.0) / 2
                score_pts_binary = (score_pts > dpg.get_value('_ScoreThres')).sum(1) > 0
                save_path = "./debug_robot_{:0>3d}.ply".format(self.object_seg_id)
                self.engine.save_ply_partial(save_path, idx=score_pts_binary)
                self.engine.load_ply(save_path)
                self.object_seg_id += 1
                print("Segmented 3D Gaussians saved to: ", save_path)

        if self.img_mode == 0:
            self.render_buffer = rgb_score.cpu().numpy().reshape(-1)
        elif self.img_mode == 1:
            self.render_buffer = depth_score
        elif self.img_mode == 2:
            self.render_buffer = sem_transed_rgb.cpu().numpy()
        
        dpg.set_value("_texture", self.render_buffer)