class_docstr: Analyse time ranges for each TracerEventType, and summarize the time.
code: def _parse_events(self, nodetrees):
      node_wrapped_trees = rebuild_node_trees(nodetrees)
      node_wrapped_threadlist = traverse_tree(node_wrapped_trees)
      # analyse user-defined summary
      for threadid, wrapped_nodes in node_wrapped_threadlist.items():
          for wrapped_node in wrapped_nodes[1:]:  # skip root node
              if wrapped_node.type == "PythonUserDefined":
                  self.add_userdefined_item(wrapped_node)
  
      # analyse all events in per stage
      thread_count = 0
      for threadid, root_wrapped_node in node_wrapped_trees.items():
          thread_count += 1
          wrapped_profiler_step_nodes = []
          for wrapped_node in root_wrapped_node.children_node:
              wrapped_profiler_step_nodes.append(wrapped_node)
          self.stage_nums = 0
          current_stage_idx = None
          for wrapped_profiler_step_node in wrapped_profiler_step_nodes:
              if wrapped_profiler_step_node.type == "ProfileStep":
                  self.process_id = (
                      wrapped_profiler_step_node.process_id
                  )
                  stage_idx = wrapped_profiler_step_node.name.split(
                      "#"
                  )[1]
                  total_time = 0
                  accumulated_stage_time = 0
                  if thread_count == 1:
                      self.add_model_perspective_item(
                          wrapped_profiler_step_node
                      )
                      self.model_perspective_items[
                          "ProfileStep"
                      ].cpu_times[
                          stage_idx
                      ] = wrapped_profiler_step_node.cpu_time
                      total_time = wrapped_profiler_step_node.cpu_time
                  self.stage_nums += 1
                  for (
                      stage_wrapped_node
                  ) in wrapped_profiler_step_node.children_node:
                      if thread_count == 1:
                          self.add_model_perspective_item(
                              stage_wrapped_node
                          )
                          if stage_wrapped_node.type in StageType:
                              self.model_perspective_items[
                                  stage_wrapped_node.type
                              ].cpu_times[
                                  stage_idx
                              ] = stage_wrapped_node.cpu_time
                          if stage_wrapped_node.type in StageType:
                              accumulated_stage_time += (
                                  stage_wrapped_node.cpu_time
                              )
                      self._fill_stage_events(
                          stage_wrapped_node, stage_idx
                      )
                  if "Other" not in self.model_perspective_items:
                      self.model_perspective_items[
                          "Other"
                      ] = ModelPerspectiveItem("Other")
                  if thread_count == 1:
                      self.model_perspective_items[
                          "Other"
                      ].add_cpu_time(
                          total_time - accumulated_stage_time
                      )
                      self.model_perspective_items["Other"].cpu_times[
                          stage_idx
                      ] = (total_time - accumulated_stage_time)
                  self._fill_stage_events(
                      wrapped_profiler_step_node,
                      stage_idx,
                      should_recursive=False,
                  )
              else:
                  self._fill_stage_events(
                      wrapped_profiler_step_node, current_stage_idx
                  )
          self._fill_stage_events(
              root_wrapped_node,
              current_stage_idx,
              should_recursive=False,
          )
  
imports: import collections
  from .utils import merge_ranges
  from .utils import merge_self_ranges
  from .utils import rebuild_node_trees
  from .utils import sum_ranges
  from .utils import traverse_tree
label_desc: Use image node_id 4 for calling the OverviewParser obj's underlying member method code with example usage: obj._parse_events(nodetrees) without return types