code: def _parse_memory(self, actor_state, last_obs):
      mem = actor_state.memory
      n = len(mem)
  
      episode_shaping_reward = np.sum(
          [exp.info["shaping_reward"] for exp in mem]
      )
      episode_env_reward = np.sum(
          [exp.info["env_reward"] for exp in mem]
      )
      episode_time = time.time() - mem[0].timestamp
  
      episode_rpm = []
      for i in range(n - 1):
          episode_rpm.append(
              [
                  mem[i].obs,
                  mem[i].action,
                  mem[i].info["shaping_reward"],
                  mem[i + 1].obs,
                  False,
              ]
          )
      episode_rpm.append(
          [
              mem[-1].obs,
              mem[-1].action,
              mem[-1].info["shaping_reward"],
              last_obs,
              not mem[-1].info["timeout"],
          ]
      )
  
      with self.memory_lock:
          self.total_steps += n
          self.add_episode_rpm(episode_rpm)
  
          if actor_state.ident % 3 == 2:  # trajectory without noise
              self.env_reward_stat.add(episode_env_reward)
              self.shaping_reward_stat.add(episode_shaping_reward)
              self.max_env_reward = max(
                  self.max_env_reward, episode_env_reward
              )
  
              if self.env_reward_stat.count > 500:
                  summary.add_scalar(
                      "recent_env_reward",
                      self.env_reward_stat.mean,
                      self.total_steps,
                  )
                  summary.add_scalar(
                      "recent_shaping_reward",
                      self.shaping_reward_stat.mean,
                      self.total_steps,
                  )
              if self.critic_loss_stat.count > 500:
                  summary.add_scalar(
                      "recent_critic_loss",
                      self.critic_loss_stat.mean,
                      self.total_steps,
                  )
              summary.add_scalar("episode_length", n, self.total_steps)
              summary.add_scalar(
                  "max_env_reward",
                  self.max_env_reward,
                  self.total_steps,
              )
              summary.add_scalar(
                  "ready_actor_num",
                  self.ready_actor_queue.qsize(),
                  self.total_steps,
              )
              summary.add_scalar(
                  "episode_time", episode_time, self.total_steps
              )
  
          self.noiselevel = self.noiselevel * NOISE_DECAY
  
imports: import os
  import parl
  import queue
  import six
  import threading
  import time
  import numpy
  from actor import Actor
  from opensim_model import OpenSimModel
  from opensim_agent import OpenSimAgent
  from parl.utils import logger, summary, get_gpu_count
  from replay_memory import ReplayMemory
  from parl.utils.window_stat import WindowStat
  from parl.remote.client import get_global_client
  from parl.utils import machine_info
label_desc: Use image node_id 5 for calling the Learner obj's underlying member method code with example usage: obj._parse_memory(actor_state, last_obs) without return types