def __init__(self, data_reader, title="Open3D for Tensorboard", width=1024, height=768): """ Args: data_reader: Open3DPluginDataReader object to read Tensorboard event files and Open3D geometry files. title (str): Window title. [Unused in WebRTC] width (int): Window width (px). height (int): Window height (px). """ self.data_reader = data_reader self.run = "." self.tags = [] self.batch_idx = 0 self.batch_size = 1 self.step = 0 self.step_limits = [0, 0] self.wall_time = 0 self.idx = 0 self.step_to_idx = dict() # self.all_tensor_events[self.tags[0]][prop][self.idx].step == self.step self.all_tensor_events = dict() self.window = None # Access only through async_event_loop self.geometry_list = [] self.init_done = threading.Event() # Notify when WebRTC is ready async_event_loop.run_sync(self._create_ui, title, width, height) self._update_scene()
def _close_window(self, request): this_window_id = request.args.get('window_id', "") if this_window_id not in self._windows.keys(): _log.warning(f"Invalid Window ID {this_window_id}") return werkzeug.exceptions.NotFound( f"Invalid Window ID {this_window_id}", response=self._ERROR_RESPONSE) async_event_loop.run_sync(self._windows[this_window_id].window.close) with self.window_lock: del self._windows[this_window_id] _log.debug(f"Window {this_window_id} closed.") return werkzeug.Response(f"Closed window {this_window_id}", content_type="text/plain", headers=self._HEADERS)
def __init__(self, context): """Instantiates Open3D plugin. Args: context: A `base_plugin.TBContext` instance. """ self._logdir = context.logdir self.data_reader = Open3DPluginDataReader(self._logdir) self.window_lock = threading.Lock() # protect self._windows self._http_api_lock = threading.Lock() self._windows = {} webrtc_server.disable_http_handshake() # Dummy window to ensure GUI remains active even if all user windows are # closed. self._dummy_window = async_event_loop.run_sync( gui.Application.instance.create_window, "Open3D Dummy Window", 32, 32)
def _update_scene(self): """Update scene by adding / removing geometry elements and redraw. """ status = "" new_geometry_list = [] for tag in self.tags: geometry_name = f"{self.run}/{tag}/b{self.batch_idx}/s{self.step}" new_geometry_list.append(geometry_name) if geometry_name not in self.geometry_list: try: geometry = self.data_reader.read_geometry( self.run, tag, self.step, self.batch_idx, self.step_to_idx) _log.debug( f"Displaying geometry {geometry_name}:{geometry}") pp_geometry = _postprocess(geometry) async_event_loop.run_sync(self.window.add_geometry, geometry_name, pp_geometry) except IOError as err: new_geometry_list.pop() err_msg = f"Error reading {geometry_name}: {err}" status = '\n'.join((status, err_msg)) _log.warning(err_msg) for current_item in self.geometry_list: if current_item not in new_geometry_list: _log.debug(f"Removing geometry {current_item}") async_event_loop.run_sync(self.window.remove_geometry, current_item) if len(self.geometry_list ) == 0: # Reset view only if previous empty scene async_event_loop.run_sync(self.window.reset_camera_to_default) else: async_event_loop.run_sync(self.window.post_redraw) self.geometry_list = new_geometry_list if not self.init_done.is_set(): self.init_done.set() _log.debug("Displaying complete!") return "OK" if len(status) == 0 else status[1:]